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