1 //
2 //
3 // Copyright 2017 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #ifndef GRPC_SRC_CORE_UTIL_DEBUG_LOCATION_H
20 #define GRPC_SRC_CORE_UTIL_DEBUG_LOCATION_H
21
22 #include <grpc/support/port_platform.h>
23
24 #include <utility>
25
26 #include "absl/strings/str_cat.h"
27
28 #if defined(__has_builtin)
29 #if __has_builtin(__builtin_FILE)
30 #define GRPC_DEFAULT_FILE __builtin_FILE()
31 #endif
32 #endif
33 #ifndef GRPC_DEFAULT_FILE
34 #define GRPC_DEFAULT_FILE "<unknown>"
35 #endif
36 #if defined(__has_builtin)
37 #if __has_builtin(__builtin_LINE)
38 #define GRPC_DEFAULT_LINE __builtin_LINE()
39 #endif
40 #endif
41 #ifndef GRPC_DEFAULT_LINE
42 #define GRPC_DEFAULT_LINE -1
43 #endif
44
45 namespace grpc_core {
46
47 class SourceLocation {
48 public:
49 // NOLINTNEXTLINE
50 SourceLocation(const char* file = GRPC_DEFAULT_FILE,
51 int line = GRPC_DEFAULT_LINE)
file_(file)52 : file_(file), line_(line) {}
file()53 const char* file() const { return file_; }
line()54 int line() const { return line_; }
55
56 private:
57 const char* file_;
58 int line_;
59 };
60
61 template <typename Sink>
AbslStringify(Sink & out,const SourceLocation & location)62 void AbslStringify(Sink& out, const SourceLocation& location) {
63 out.Append(absl::StrCat("[", location.file(), ":", location.line(), "]"));
64 }
65
66 // Used for tracking file and line where a call is made for debug builds.
67 // No-op for non-debug builds.
68 // Callers can use the DEBUG_LOCATION macro in either case.
69 #ifndef NDEBUG
70 class DebugLocation {
71 public:
72 DebugLocation(const char* file = GRPC_DEFAULT_FILE,
73 int line = GRPC_DEFAULT_LINE)
location_(file,line)74 : location_(file, line) {}
DebugLocation(SourceLocation location)75 explicit DebugLocation(SourceLocation location) : location_(location) {}
file()76 const char* file() const { return location_.file(); }
line()77 int line() const { return location_.line(); }
78
79 private:
80 SourceLocation location_;
81 };
82 #else
83 class DebugLocation {
84 public:
DebugLocation()85 DebugLocation() {}
DebugLocation(SourceLocation)86 explicit DebugLocation(SourceLocation) {}
DebugLocation(const char *,int)87 DebugLocation(const char* /* file */, int /* line */) {}
file()88 const char* file() const { return nullptr; }
line()89 int line() const { return -1; }
90 };
91 #endif
92
93 template <typename T>
94 struct ValueWithDebugLocation {
95 // NOLINTNEXTLINE
96 ValueWithDebugLocation(T&& value, DebugLocation debug_location = {})
valueValueWithDebugLocation97 : value(std::forward<T>(value)), debug_location(debug_location) {}
98 T value;
99 GPR_NO_UNIQUE_ADDRESS DebugLocation debug_location;
100 };
101
102 #define DEBUG_LOCATION ::grpc_core::DebugLocation(__FILE__, __LINE__)
103
104 } // namespace grpc_core
105
106 #endif // GRPC_SRC_CORE_UTIL_DEBUG_LOCATION_H
107