1651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===- unittests/AST/EvaluateAsRValueTest.cpp -----------------------------===// 2651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// 3651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// The LLVM Compiler Infrastructure 4651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// 5651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// This file is distributed under the University of Illinois Open Source 6651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// License. See LICENSE.TXT for details. 7651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// 8651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===----------------------------------------------------------------------===// 9651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// 10651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// \file 11651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// \brief Unit tests for evaluation of constant initializers. 12651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// 13651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===----------------------------------------------------------------------===// 14651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 15651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <map> 16651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <string> 17651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 18651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/ASTConsumer.h" 19651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/ASTContext.h" 20651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/RecursiveASTVisitor.h" 21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Tooling/Tooling.h" 22651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "gtest/gtest.h" 23651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/ASTConsumer.h" 25651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 26651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesusing namespace clang::tooling; 27651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace { 29651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// For each variable name encountered, whether its initializer was a 30651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// constant. 31651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinestypedef std::map<std::string, bool> VarInfoMap; 32651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 33651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Records information on variable initializers to a map. 34651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass EvaluateConstantInitializersVisitor 35651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : public clang::RecursiveASTVisitor<EvaluateConstantInitializersVisitor> { 36651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines public: 37651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines explicit EvaluateConstantInitializersVisitor(VarInfoMap &VarInfo) 38651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : VarInfo(VarInfo) {} 39651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 40651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// \brief Checks that isConstantInitializer and EvaluateAsRValue agree 41651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// and don't crash. 42651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// 43651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// For each VarDecl with an initializer this also records in VarInfo 44651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// whether the initializer could be evaluated as a constant. 45651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool VisitVarDecl(const clang::VarDecl *VD) { 46651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const clang::Expr *Init = VD->getInit()) { 47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines clang::Expr::EvalResult Result; 48651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool WasEvaluated = Init->EvaluateAsRValue(Result, VD->getASTContext()); 49651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines VarInfo[VD->getNameAsString()] = WasEvaluated; 50651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EXPECT_EQ(WasEvaluated, Init->isConstantInitializer(VD->getASTContext(), 51651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines false /*ForRef*/)); 52651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 53651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 54651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 55651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 56651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines private: 57651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines VarInfoMap &VarInfo; 58651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 60651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass EvaluateConstantInitializersAction : public clang::ASTFrontendAction { 61651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines public: 62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &Compiler, 63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::StringRef FilePath) override { 64651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return new Consumer; 65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines private: 68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines class Consumer : public clang::ASTConsumer { 69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines public: 70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ~Consumer() override {} 71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void HandleTranslationUnit(clang::ASTContext &Ctx) override { 73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines VarInfoMap VarInfo; 74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EvaluateConstantInitializersVisitor Evaluator(VarInfo); 75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Evaluator.TraverseDecl(Ctx.getTranslationUnitDecl()); 76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EXPECT_EQ(2u, VarInfo.size()); 77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EXPECT_FALSE(VarInfo["Dependent"]); 78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EXPECT_TRUE(VarInfo["Constant"]); 79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EXPECT_EQ(2u, VarInfo.size()); 80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines }; 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 85651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST(EvaluateAsRValue, FailsGracefullyForUnknownTypes) { 86651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // This is a regression test; the AST library used to trigger assertion 87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // failures because it assumed that the type of initializers was always 88651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // known (which is true only after template instantiation). 89651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string ModesToTest[] = {"-std=c++03", "-std=c++11", "-std=c++1y"}; 90651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (std::string const &Mode : ModesToTest) { 91651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> Args(1, Mode); 92651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Args.push_back("-fno-delayed-template-parsing"); 93651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ASSERT_TRUE(runToolOnCodeWithArgs( 94651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new EvaluateConstantInitializersAction(), 95651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "template <typename T>" 96651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "struct vector {" 97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " explicit vector(int size);" 98651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "};" 99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "template <typename R>" 100651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "struct S {" 101651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " vector<R> intervals() const {" 102651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " vector<R> Dependent(2);" 103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " return Dependent;" 104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " }" 105651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "};" 106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "void doSomething() {" 107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " int Constant = 2 + 2;" 108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " (void) Constant;" 109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "}", 110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Args)); 111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 113