summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2016-04-08 09:51:06 +0000
committerAlexander Kornienko <alexfh@google.com>2016-04-08 09:51:06 +0000
commit477e5d8d3160367e03edc1343900e87267b22fac (patch)
treef5e5a05f82971dca8c0310439c0ffe5470c706fa /clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp
parentad659c3400d03fe1797c5b00eb825d4b6b745686 (diff)
downloadbcm5719-llvm-477e5d8d3160367e03edc1343900e87267b22fac.tar.gz
bcm5719-llvm-477e5d8d3160367e03edc1343900e87267b22fac.zip
[clang-tidy] cppcoreguidelines-interfaces-global-init
Summary: This check flags initializers of globals that access extern objects, and therefore can lead to order-of-initialization problems (this recommandation is part of CPP core guidelines). Note that this only checks half of the guideline for now (it does not enforce using constexpr functions). Reviewers: aaron.ballman, alexfh Subscribers: aaron.ballman, etienneb, Eugene.Zelenko, cfe-commits Patch by Clement Courbet! Differential Revision: http://reviews.llvm.org/D18649 llvm-svn: 265774
Diffstat (limited to 'clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp')
-rw-r--r--clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp
new file mode 100644
index 00000000000..51f79e522c0
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t
+
+constexpr int makesInt() { return 3; }
+constexpr int takesInt(int i) { return i + 1; }
+constexpr int takesIntPtr(int *i) { return *i; }
+
+extern int ExternGlobal;
+static int GlobalScopeBadInit1 = ExternGlobal;
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit2 = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+namespace ns {
+static int NamespaceScope = makesInt();
+static int NamespaceScopeBadInit = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+struct A {
+ static int ClassScope;
+ static int ClassScopeBadInit;
+};
+
+int A::ClassScopeBadInit = takesInt(ExternGlobal);
+// CHECK-MESSAGES: [[@LINE-1]]:8: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal'
+
+static int FromClassBadInit = takesInt(A::ClassScope);
+// CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope'
+} // namespace ns
+
+// "const int B::I;" is fine, it just ODR-defines B::I. See [9.4.3] Static
+// members [class.static]. However the ODR-definitions are not in the right
+// order (C::I after C::J, see [3.6.2.3]).
+class B1 {
+ static const int I = 0;
+ static const int J = I;
+};
+const int B1::J;
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I'
+const int B1::I;
+
+void f() {
+ // This is fine, it's executed after dynamic initialization occurs.
+ static int G = takesInt(ExternGlobal);
+}
+
+// Declaration then definition then usage is fine.
+extern int ExternGlobal2;
+extern int ExternGlobal2;
+int ExternGlobal2 = 123;
+static int GlobalScopeGoodInit1 = ExternGlobal2;
+
+
+// Defined global variables are fine:
+static int GlobalScope = makesInt();
+static int GlobalScopeGoodInit2 = takesInt(GlobalScope);
+static int GlobalScope2 = takesInt(ns::NamespaceScope);
+// Enums are fine.
+enum Enum { kEnumValue = 1 };
+static int GlobalScopeFromEnum = takesInt(kEnumValue);
+
+// Leave constexprs alone.
+extern constexpr int GlobalScopeConstexpr = makesInt();
+static constexpr int GlobalScopeConstexprOk =
+ takesInt(GlobalScopeConstexpr);
+
+// This is a pretty common instance: People are usually not using constexpr, but
+// this is what they should write:
+static constexpr const char kValue[] = "value";
+constexpr int Fingerprint(const char *value) { return 0; }
+static int kFingerprint = Fingerprint(kValue);
+
+// This is fine because the ODR-definitions are in the right order (C::J after
+// C::I).
+class B2 {
+ static const int I = 0;
+ static const int J = I;
+};
+const int B2::I;
+const int B2::J;
+
OpenPOWER on IntegriCloud