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
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 1da2ca8..99dd96c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -62,7 +62,7 @@
public:
CheckDefaultArgumentVisitor(Expr *defarg, Sema *s)
- : DefaultArg(defarg), S(s) {}
+ : DefaultArg(defarg), S(s) {}
bool VisitExpr(Expr *Node);
bool VisitDeclRefExpr(DeclRefExpr *DRE);
@@ -13025,7 +13025,7 @@
// If we already have the in-class initializer nothing needs to be done.
if (Field->getInClassInitializer())
- return CXXDefaultInitExpr::Create(Context, Loc, Field);
+ return CXXDefaultInitExpr::Create(Context, Loc, Field, CurContext);
// If we might have already tried and failed to instantiate, don't try again.
if (Field->isInvalidDecl())
@@ -13066,7 +13066,7 @@
Field->setInvalidDecl();
return ExprError();
}
- return CXXDefaultInitExpr::Create(Context, Loc, Field);
+ return CXXDefaultInitExpr::Create(Context, Loc, Field, CurContext);
}
// DR1351:
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index eb2bfec..59b919b 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1289,6 +1289,7 @@
case Expr::PredefinedExprClass:
case Expr::SizeOfPackExprClass:
case Expr::StringLiteralClass:
+ case Expr::SourceLocExprClass:
// These expressions can never throw.
return CT_Cannot;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index f005838..fbbdc66 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1683,20 +1683,8 @@
Diag(RemovalDiagLoc, RemovalDiag);
}
-
- QualType CharTyConst = CharTy;
- // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
- if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
- CharTyConst.addConst();
-
- CharTyConst = Context.adjustStringLiteralBaseType(CharTyConst);
-
- // Get an array type for the string, according to C99 6.4.5. This includes
- // the nul terminator character as well as the string length for pascal
- // strings.
- QualType StrTy = Context.getConstantArrayType(
- CharTyConst, llvm::APInt(32, Literal.GetNumStringChars() + 1),
- ArrayType::Normal, 0);
+ QualType StrTy =
+ Context.getStringLiteralArrayType(CharTy, Literal.GetNumStringChars());
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
@@ -4873,7 +4861,7 @@
FunctionDecl *FD, ParmVarDecl *Param) {
if (CheckCXXDefaultArgExpr(CallLoc, FD, Param))
return ExprError();
- return CXXDefaultArgExpr::Create(Context, CallLoc, Param);
+ return CXXDefaultArgExpr::Create(Context, CallLoc, Param, CurContext);
}
Sema::VariadicCallType
@@ -5138,8 +5126,7 @@
} else {
assert(Param && "can't use default arguments without a known callee");
- ExprResult ArgExpr =
- BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
+ ExprResult ArgExpr = BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
if (ArgExpr.isInvalid())
return true;
@@ -14097,6 +14084,20 @@
return new (Context) GNUNullExpr(Ty, TokenLoc);
}
+ExprResult Sema::ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind,
+ SourceLocation BuiltinLoc,
+ SourceLocation RPLoc) {
+ return BuildSourceLocExpr(Kind, BuiltinLoc, RPLoc, CurContext);
+}
+
+ExprResult Sema::BuildSourceLocExpr(SourceLocExpr::IdentKind Kind,
+ SourceLocation BuiltinLoc,
+ SourceLocation RPLoc,
+ DeclContext *ParentContext) {
+ return new (Context)
+ SourceLocExpr(Context, Kind, BuiltinLoc, RPLoc, ParentContext);
+}
+
bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp,
bool Diagnose) {
if (!getLangOpts().ObjC)
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 818a981..040cfdd 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -1097,12 +1097,7 @@
// The type of @encode is the same as the type of the corresponding string,
// which is an array type.
- StrTy = Context.CharTy;
- // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
- if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
- StrTy.addConst();
- StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
- ArrayType::Normal, 0);
+ StrTy = Context.getStringLiteralArrayType(Context.CharTy, Str.size());
}
return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index fc8209e..f8b9b34 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2713,9 +2713,9 @@
/// By default, builds a new default-argument expression, which does not
/// require any semantic analysis. Subclasses may override this routine to
/// provide different behavior.
- ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc,
- ParmVarDecl *Param) {
- return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param);
+ ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, ParmVarDecl *Param) {
+ return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param,
+ getSema().CurContext);
}
/// Build a new C++11 default-initialization expression.
@@ -2725,7 +2725,8 @@
/// routine to provide different behavior.
ExprResult RebuildCXXDefaultInitExpr(SourceLocation Loc,
FieldDecl *Field) {
- return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field);
+ return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field,
+ getSema().CurContext);
}
/// Build a new C++ zero-initialization expression.
@@ -2979,6 +2980,18 @@
RParenLoc, Length, PartialArgs);
}
+ /// Build a new expression representing a call to a source location
+ /// builtin.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildSourceLocExpr(SourceLocExpr::IdentKind Kind,
+ SourceLocation BuiltinLoc,
+ SourceLocation RPLoc,
+ DeclContext *ParentContext) {
+ return getSema().BuildSourceLocExpr(Kind, BuiltinLoc, RPLoc, ParentContext);
+ }
+
/// Build a new Objective-C boxed expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -10132,6 +10145,19 @@
return getDerived().TransformCallExpr(E);
}
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformSourceLocExpr(SourceLocExpr *E) {
+ bool NeedRebuildFunc = E->getIdentKind() == SourceLocExpr::Function &&
+ getSema().CurContext != E->getParentContext();
+
+ if (!getDerived().AlwaysRebuild() && !NeedRebuildFunc)
+ return E;
+
+ return getDerived().RebuildSourceLocExpr(E->getIdentKind(), E->getBeginLoc(),
+ E->getEndLoc(),
+ getSema().CurContext);
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
@@ -10358,8 +10384,8 @@
if (!Param)
return ExprError();
- if (!getDerived().AlwaysRebuild() &&
- Param == E->getParam())
+ if (!getDerived().AlwaysRebuild() && Param == E->getParam() &&
+ E->getUsedContext() == SemaRef.CurContext)
return E;
return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param);
@@ -10373,7 +10399,8 @@
if (!Field)
return ExprError();
- if (!getDerived().AlwaysRebuild() && Field == E->getField())
+ if (!getDerived().AlwaysRebuild() && Field == E->getField() &&
+ E->getUsedContext() == SemaRef.CurContext)
return E;
return getDerived().RebuildCXXDefaultInitExpr(E->getExprLoc(), Field);