1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/AST/ASTConsumer.h" |
15 | #include "clang/AST/ASTConsumer.h" |
16 | #include "clang/AST/ASTContext.h" |
17 | #include "clang/AST/RecursiveASTVisitor.h" |
18 | #include "clang/Tooling/Tooling.h" |
19 | #include "gtest/gtest.h" |
20 | #include <map> |
21 | #include <string> |
22 | |
23 | using namespace clang::tooling; |
24 | |
25 | namespace { |
26 | |
27 | |
28 | typedef std::map<std::string, bool> VarInfoMap; |
29 | |
30 | |
31 | class EvaluateConstantInitializersVisitor |
32 | : public clang::RecursiveASTVisitor<EvaluateConstantInitializersVisitor> { |
33 | public: |
34 | explicit EvaluateConstantInitializersVisitor(VarInfoMap &VarInfo) |
35 | : VarInfo(VarInfo) {} |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | bool VisitVarDecl(const clang::VarDecl *VD) { |
43 | if (const clang::Expr *Init = VD->getInit()) { |
44 | clang::Expr::EvalResult Result; |
45 | bool WasEvaluated = Init->EvaluateAsRValue(Result, VD->getASTContext()); |
46 | VarInfo[VD->getNameAsString()] = WasEvaluated; |
47 | EXPECT_EQ(WasEvaluated, Init->isConstantInitializer(VD->getASTContext(), |
48 | false )); |
49 | } |
50 | return true; |
51 | } |
52 | |
53 | private: |
54 | VarInfoMap &VarInfo; |
55 | }; |
56 | |
57 | class EvaluateConstantInitializersAction : public clang::ASTFrontendAction { |
58 | public: |
59 | std::unique_ptr<clang::ASTConsumer> |
60 | CreateASTConsumer(clang::CompilerInstance &Compiler, |
61 | llvm::StringRef FilePath) override { |
62 | return llvm::make_unique<Consumer>(); |
63 | } |
64 | |
65 | private: |
66 | class Consumer : public clang::ASTConsumer { |
67 | public: |
68 | ~Consumer() override {} |
69 | |
70 | void HandleTranslationUnit(clang::ASTContext &Ctx) override { |
71 | VarInfoMap VarInfo; |
72 | EvaluateConstantInitializersVisitor Evaluator(VarInfo); |
73 | Evaluator.TraverseDecl(Ctx.getTranslationUnitDecl()); |
74 | EXPECT_EQ(2u, VarInfo.size()); |
75 | EXPECT_FALSE(VarInfo["Dependent"]); |
76 | EXPECT_TRUE(VarInfo["Constant"]); |
77 | EXPECT_EQ(2u, VarInfo.size()); |
78 | } |
79 | }; |
80 | }; |
81 | } |
82 | |
83 | TEST(EvaluateAsRValue, FailsGracefullyForUnknownTypes) { |
84 | |
85 | |
86 | |
87 | std::string ModesToTest[] = {"-std=c++03", "-std=c++11", "-std=c++1y"}; |
88 | for (std::string const &Mode : ModesToTest) { |
89 | std::vector<std::string> Args(1, Mode); |
90 | Args.push_back("-fno-delayed-template-parsing"); |
91 | ASSERT_TRUE(runToolOnCodeWithArgs( |
92 | new EvaluateConstantInitializersAction(), |
93 | "template <typename T>" |
94 | "struct vector {" |
95 | " explicit vector(int size);" |
96 | "};" |
97 | "template <typename R>" |
98 | "struct S {" |
99 | " vector<R> intervals() const {" |
100 | " vector<R> Dependent(2);" |
101 | " return Dependent;" |
102 | " }" |
103 | "};" |
104 | "void doSomething() {" |
105 | " int Constant = 2 + 2;" |
106 | " (void) Constant;" |
107 | "}", |
108 | Args)); |
109 | } |
110 | } |
111 | |