summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2019-05-16 21:04:15 +0000
committerEric Fiselier <eric@efcs.ca>2019-05-16 21:04:15 +0000
commit708afb56c125ca4f7db7070e836860076c7eafbc (patch)
tree3dee8820f6b797ab01e7621f7eab44a615fced41 /clang/lib/AST/ExprConstant.cpp
parente7b680478c8e15e92af6706da0edaeab8708e49e (diff)
downloadbcm5719-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.cpp37
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:
OpenPOWER on IntegriCloud