xref: /minix3/external/bsd/llvm/dist/clang/unittests/AST/EvaluateAsRValueTest.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //===- unittests/AST/EvaluateAsRValueTest.cpp -----------------------------===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // \file
11*0a6a1f1dSLionel Sambuc // \brief Unit tests for evaluation of constant initializers.
12*0a6a1f1dSLionel Sambuc //
13*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
14*0a6a1f1dSLionel Sambuc 
15*0a6a1f1dSLionel Sambuc #include "clang/AST/ASTConsumer.h"
16*0a6a1f1dSLionel Sambuc #include "clang/AST/ASTConsumer.h"
17*0a6a1f1dSLionel Sambuc #include "clang/AST/ASTContext.h"
18*0a6a1f1dSLionel Sambuc #include "clang/AST/RecursiveASTVisitor.h"
19*0a6a1f1dSLionel Sambuc #include "clang/Tooling/Tooling.h"
20*0a6a1f1dSLionel Sambuc #include "gtest/gtest.h"
21*0a6a1f1dSLionel Sambuc #include <map>
22*0a6a1f1dSLionel Sambuc #include <string>
23*0a6a1f1dSLionel Sambuc 
24*0a6a1f1dSLionel Sambuc using namespace clang::tooling;
25*0a6a1f1dSLionel Sambuc 
26*0a6a1f1dSLionel Sambuc namespace {
27*0a6a1f1dSLionel Sambuc // For each variable name encountered, whether its initializer was a
28*0a6a1f1dSLionel Sambuc // constant.
29*0a6a1f1dSLionel Sambuc typedef std::map<std::string, bool> VarInfoMap;
30*0a6a1f1dSLionel Sambuc 
31*0a6a1f1dSLionel Sambuc /// \brief Records information on variable initializers to a map.
32*0a6a1f1dSLionel Sambuc class EvaluateConstantInitializersVisitor
33*0a6a1f1dSLionel Sambuc     : public clang::RecursiveASTVisitor<EvaluateConstantInitializersVisitor> {
34*0a6a1f1dSLionel Sambuc  public:
EvaluateConstantInitializersVisitor(VarInfoMap & VarInfo)35*0a6a1f1dSLionel Sambuc   explicit EvaluateConstantInitializersVisitor(VarInfoMap &VarInfo)
36*0a6a1f1dSLionel Sambuc       : VarInfo(VarInfo) {}
37*0a6a1f1dSLionel Sambuc 
38*0a6a1f1dSLionel Sambuc   /// \brief Checks that isConstantInitializer and EvaluateAsRValue agree
39*0a6a1f1dSLionel Sambuc   /// and don't crash.
40*0a6a1f1dSLionel Sambuc   ///
41*0a6a1f1dSLionel Sambuc   /// For each VarDecl with an initializer this also records in VarInfo
42*0a6a1f1dSLionel Sambuc   /// whether the initializer could be evaluated as a constant.
VisitVarDecl(const clang::VarDecl * VD)43*0a6a1f1dSLionel Sambuc   bool VisitVarDecl(const clang::VarDecl *VD) {
44*0a6a1f1dSLionel Sambuc     if (const clang::Expr *Init = VD->getInit()) {
45*0a6a1f1dSLionel Sambuc       clang::Expr::EvalResult Result;
46*0a6a1f1dSLionel Sambuc       bool WasEvaluated = Init->EvaluateAsRValue(Result, VD->getASTContext());
47*0a6a1f1dSLionel Sambuc       VarInfo[VD->getNameAsString()] = WasEvaluated;
48*0a6a1f1dSLionel Sambuc       EXPECT_EQ(WasEvaluated, Init->isConstantInitializer(VD->getASTContext(),
49*0a6a1f1dSLionel Sambuc                                                           false /*ForRef*/));
50*0a6a1f1dSLionel Sambuc     }
51*0a6a1f1dSLionel Sambuc     return true;
52*0a6a1f1dSLionel Sambuc   }
53*0a6a1f1dSLionel Sambuc 
54*0a6a1f1dSLionel Sambuc  private:
55*0a6a1f1dSLionel Sambuc   VarInfoMap &VarInfo;
56*0a6a1f1dSLionel Sambuc };
57*0a6a1f1dSLionel Sambuc 
58*0a6a1f1dSLionel Sambuc class EvaluateConstantInitializersAction : public clang::ASTFrontendAction {
59*0a6a1f1dSLionel Sambuc  public:
60*0a6a1f1dSLionel Sambuc    std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance & Compiler,llvm::StringRef FilePath)61*0a6a1f1dSLionel Sambuc    CreateASTConsumer(clang::CompilerInstance &Compiler,
62*0a6a1f1dSLionel Sambuc                      llvm::StringRef FilePath) override {
63*0a6a1f1dSLionel Sambuc      return llvm::make_unique<Consumer>();
64*0a6a1f1dSLionel Sambuc   }
65*0a6a1f1dSLionel Sambuc 
66*0a6a1f1dSLionel Sambuc  private:
67*0a6a1f1dSLionel Sambuc   class Consumer : public clang::ASTConsumer {
68*0a6a1f1dSLionel Sambuc    public:
~Consumer()69*0a6a1f1dSLionel Sambuc     ~Consumer() override {}
70*0a6a1f1dSLionel Sambuc 
HandleTranslationUnit(clang::ASTContext & Ctx)71*0a6a1f1dSLionel Sambuc     void HandleTranslationUnit(clang::ASTContext &Ctx) override {
72*0a6a1f1dSLionel Sambuc       VarInfoMap VarInfo;
73*0a6a1f1dSLionel Sambuc       EvaluateConstantInitializersVisitor Evaluator(VarInfo);
74*0a6a1f1dSLionel Sambuc       Evaluator.TraverseDecl(Ctx.getTranslationUnitDecl());
75*0a6a1f1dSLionel Sambuc       EXPECT_EQ(2u, VarInfo.size());
76*0a6a1f1dSLionel Sambuc       EXPECT_FALSE(VarInfo["Dependent"]);
77*0a6a1f1dSLionel Sambuc       EXPECT_TRUE(VarInfo["Constant"]);
78*0a6a1f1dSLionel Sambuc       EXPECT_EQ(2u, VarInfo.size());
79*0a6a1f1dSLionel Sambuc     }
80*0a6a1f1dSLionel Sambuc   };
81*0a6a1f1dSLionel Sambuc };
82*0a6a1f1dSLionel Sambuc }
83*0a6a1f1dSLionel Sambuc 
TEST(EvaluateAsRValue,FailsGracefullyForUnknownTypes)84*0a6a1f1dSLionel Sambuc TEST(EvaluateAsRValue, FailsGracefullyForUnknownTypes) {
85*0a6a1f1dSLionel Sambuc   // This is a regression test; the AST library used to trigger assertion
86*0a6a1f1dSLionel Sambuc   // failures because it assumed that the type of initializers was always
87*0a6a1f1dSLionel Sambuc   // known (which is true only after template instantiation).
88*0a6a1f1dSLionel Sambuc   std::string ModesToTest[] = {"-std=c++03", "-std=c++11", "-std=c++1y"};
89*0a6a1f1dSLionel Sambuc   for (std::string const &Mode : ModesToTest) {
90*0a6a1f1dSLionel Sambuc     std::vector<std::string> Args(1, Mode);
91*0a6a1f1dSLionel Sambuc     Args.push_back("-fno-delayed-template-parsing");
92*0a6a1f1dSLionel Sambuc     ASSERT_TRUE(runToolOnCodeWithArgs(
93*0a6a1f1dSLionel Sambuc       new EvaluateConstantInitializersAction(),
94*0a6a1f1dSLionel Sambuc       "template <typename T>"
95*0a6a1f1dSLionel Sambuc       "struct vector {"
96*0a6a1f1dSLionel Sambuc       "  explicit vector(int size);"
97*0a6a1f1dSLionel Sambuc       "};"
98*0a6a1f1dSLionel Sambuc       "template <typename R>"
99*0a6a1f1dSLionel Sambuc       "struct S {"
100*0a6a1f1dSLionel Sambuc       "  vector<R> intervals() const {"
101*0a6a1f1dSLionel Sambuc       "    vector<R> Dependent(2);"
102*0a6a1f1dSLionel Sambuc       "    return Dependent;"
103*0a6a1f1dSLionel Sambuc       "  }"
104*0a6a1f1dSLionel Sambuc       "};"
105*0a6a1f1dSLionel Sambuc       "void doSomething() {"
106*0a6a1f1dSLionel Sambuc       "  int Constant = 2 + 2;"
107*0a6a1f1dSLionel Sambuc       "  (void) Constant;"
108*0a6a1f1dSLionel Sambuc       "}",
109*0a6a1f1dSLionel Sambuc       Args));
110*0a6a1f1dSLionel Sambuc   }
111*0a6a1f1dSLionel Sambuc }
112