diff options
author | Eric Fiselier <eric@efcs.ca> | 2019-05-16 21:04:15 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2019-05-16 21:04:15 +0000 |
commit | 708afb56c125ca4f7db7070e836860076c7eafbc (patch) | |
tree | 3dee8820f6b797ab01e7621f7eab44a615fced41 /clang/lib/AST/ExprConstant.cpp | |
parent | e7b680478c8e15e92af6706da0edaeab8708e49e (diff) | |
download | bcm5719-llvm-708afb56c125ca4f7db7070e836860076c7eafbc.tar.gz bcm5719-llvm-708afb56c125ca4f7db7070e836860076c7eafbc.zip |
Implement __builtin_LINE() et. al. to support source location capture.
Summary:
This patch implements the source location builtins `__builtin_LINE(), `__builtin_FUNCTION()`, `__builtin_FILE()` and `__builtin_COLUMN()`. These builtins are needed to implement [`std::experimental::source_location`](https://rawgit.com/cplusplus/fundamentals-ts/v2/main.html#reflection.src_loc.creation).
With the exception of `__builtin_COLUMN`, GCC also implements these builtins, and Clangs behavior is intended to match as closely as possible.
Reviewers: rsmith, joerg, aaron.ballman, bogner, majnemer, shafik, martong
Reviewed By: rsmith
Subscribers: rnkovacs, loskutov, riccibruno, mgorny, kunitoki, alexr, majnemer, hfinkel, cfe-commits
Differential Revision: https://reviews.llvm.org/D37035
llvm-svn: 360937
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5bedddda57a..29b6d12c2f2 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -37,6 +37,7 @@ #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/CurrentSourceLocExprScope.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Expr.h" #include "clang/AST/OSLog.h" @@ -64,6 +65,9 @@ namespace { struct CallStackFrame; struct EvalInfo; + using SourceLocExprScopeGuard = + CurrentSourceLocExprScope::SourceLocExprScopeGuard; + static QualType getType(APValue::LValueBase B) { if (!B) return QualType(); if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) { @@ -106,12 +110,12 @@ namespace { /// Get an LValue path entry, which is known to not be an array index, as a /// field declaration. static const FieldDecl *getAsField(APValue::LValuePathEntry E) { - return dyn_cast<FieldDecl>(E.getAsBaseOrMember().getPointer()); + return dyn_cast_or_null<FieldDecl>(E.getAsBaseOrMember().getPointer()); } /// Get an LValue path entry, which is known to not be an array index, as a /// base class declaration. static const CXXRecordDecl *getAsBaseClass(APValue::LValuePathEntry E) { - return dyn_cast<CXXRecordDecl>(E.getAsBaseOrMember().getPointer()); + return dyn_cast_or_null<CXXRecordDecl>(E.getAsBaseOrMember().getPointer()); } /// Determine whether this LValue path entry for a base class names a virtual /// base class. @@ -464,6 +468,10 @@ namespace { /// parameters' function scope indices. APValue *Arguments; + /// Source location information about the default argument or default + /// initializer expression we're evaluating, if any. + CurrentSourceLocExprScope CurSourceLocExprScope; + // Note that we intentionally use std::map here so that references to // values are stable. typedef std::pair<const void *, unsigned> MapKeyTy; @@ -2732,6 +2740,9 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived, /// Extract the value of a character from a string literal. static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, uint64_t Index) { + assert(!isa<SourceLocExpr>(Lit) && + "SourceLocExpr should have already been converted to a StringLiteral"); + // FIXME: Support MakeStringConstant if (const auto *ObjCEnc = dyn_cast<ObjCEncodeExpr>(Lit)) { std::string Str; @@ -3469,6 +3480,7 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // Check for special cases where there is no existing APValue to look at. const Expr *Base = LVal.Base.dyn_cast<const Expr*>(); + if (Base && !LVal.getLValueCallIndex() && !Type.isVolatileQualified()) { if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(Base)) { // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the @@ -5242,6 +5254,7 @@ public: { return StmtVisitorTy::Visit(E->getReplacement()); } bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { TempVersionRAII RAII(*Info.CurrentCall); + SourceLocExprScopeGuard Guard(E, Info.CurrentCall->CurSourceLocExprScope); return StmtVisitorTy::Visit(E->getExpr()); } bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { @@ -5249,8 +5262,10 @@ public: // The initializer may not have been parsed yet, or might be erroneous. if (!E->getExpr()) return Error(E); + SourceLocExprScopeGuard Guard(E, Info.CurrentCall->CurSourceLocExprScope); return StmtVisitorTy::Visit(E->getExpr()); } + // We cannot create any objects for which cleanups are required, so there is // nothing to do here; all cleanups must come from unevaluated subexpressions. bool VisitExprWithCleanups(const ExprWithCleanups *E) @@ -6327,6 +6342,14 @@ public: return true; } + bool VisitSourceLocExpr(const SourceLocExpr *E) { + assert(E->isStringType() && "SourceLocExpr isn't a pointer type?"); + APValue LValResult = E->EvaluateInContext( + Info.Ctx, Info.CurrentCall->CurSourceLocExprScope.getDefaultExpr()); + Result.setFrom(Info.Ctx, LValResult); + return true; + } + // FIXME: Missing: @protocol, @selector }; } // end anonymous namespace @@ -7982,7 +8005,7 @@ public: bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); - + bool VisitSourceLocExpr(const SourceLocExpr *E); // FIXME: Missing: array subscript of vector, member of vector }; @@ -8058,6 +8081,12 @@ static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) { return true; } +bool IntExprEvaluator::VisitSourceLocExpr(const SourceLocExpr *E) { + APValue Evaluated = E->EvaluateInContext( + Info.Ctx, Info.CurrentCall->CurSourceLocExprScope.getDefaultExpr()); + return Success(Evaluated, E); +} + static bool EvaluateFixedPoint(const Expr *E, APFixedPoint &Result, EvalInfo &Info) { if (E->getType()->isFixedPointType()) { @@ -11899,7 +11928,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: - // GCC considers the GNU __null value to be an integral constant expression. + case Expr::SourceLocExprClass: return NoDiag(); case Expr::SubstNonTypeTemplateParmExprClass: |