diff options
author | Alexander Kornienko <alexfh@google.com> | 2016-04-08 09:51:06 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2016-04-08 09:51:06 +0000 |
commit | 477e5d8d3160367e03edc1343900e87267b22fac (patch) | |
tree | f5e5a05f82971dca8c0310439c0ffe5470c706fa /clang-tools-extra/test/clang-tidy/cppcoreguidelines-interfaces-global-init.cpp | |
parent | ad659c3400d03fe1797c5b00eb825d4b6b745686 (diff) | |
download | bcm5719-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.cpp | 84 |
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; + |