r360937 - Implement __builtin_LINE() et. al. to support source location capture.
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Thu May 16 14:04:17 PDT 2019
Author: ericwf
Date: Thu May 16 14:04:15 2019
New Revision: 360937
URL: http://llvm.org/viewvc/llvm-project?rev=360937&view=rev
Log:
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
Added:
cfe/trunk/include/clang/AST/CurrentSourceLocExprScope.h
cfe/trunk/test/CodeGenCXX/builtin-source-location.cpp
cfe/trunk/test/CodeGenCXX/builtin_FUNCTION.cpp
cfe/trunk/test/CodeGenCXX/builtin_LINE.cpp
cfe/trunk/test/Parser/builtin_source_location.c
cfe/trunk/test/Sema/source_location.c
cfe/trunk/test/SemaCXX/Inputs/source-location-file.h
cfe/trunk/test/SemaCXX/source_location.cpp
Modified:
cfe/trunk/docs/LanguageExtensions.rst
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
cfe/trunk/include/clang/AST/Stmt.h
cfe/trunk/include/clang/Basic/StmtNodes.td
cfe/trunk/include/clang/Basic/TokenKinds.def
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/include/clang/Serialization/ASTBitCodes.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/AST/ExprClassification.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/AST/ItaniumMangle.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/AST/StmtProfile.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
cfe/trunk/lib/CodeGen/CGExprComplex.cpp
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprObjC.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/CodeGenCXX/debug-info-line.cpp
cfe/trunk/tools/libclang/CXCursor.cpp
Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Thu May 16 14:04:15 2019
@@ -2300,6 +2300,61 @@ automatically will insert one if the fir
token `none`. If a user calls `__builin_suspend`, clang will insert `token none`
as the first argument to the intrinsic.
+Source location builtins
+------------------------
+
+Clang provides experimental builtins to support C++ standard library implementation
+of ``std::experimental::source_location`` as specified in http://wg21.link/N4600.
+With the exception of ``__builtin_COLUMN``, these builtins are also implemented by
+GCC.
+
+**Syntax**:
+
+.. code-block:: c
+
+ const char *__builtin_FILE();
+ const char *__builtin_FUNCTION();
+ unsigned __builtin_LINE();
+ unsigned __builtin_COLUMN(); // Clang only
+
+**Example of use**:
+
+.. code-block:: c++
+
+ void my_assert(bool pred, int line = __builtin_LINE(), // Captures line of caller
+ const char* file = __builtin_FILE(),
+ const char* function = __builtin_FUNCTION()) {
+ if (pred) return;
+ printf("%s:%d assertion failed in function %s\n", file, line, function);
+ std::abort();
+ }
+
+ struct MyAggregateType {
+ int x;
+ int line = __builtin_LINE(); // captures line where aggregate initialization occurs
+ };
+ static_assert(MyAggregateType{42}.line == __LINE__);
+
+ struct MyClassType {
+ int line = __builtin_LINE(); // captures line of the constructor used during initialization
+ constexpr MyClassType(int) { assert(line == __LINE__); }
+ };
+
+**Description**:
+
+The builtins ``__builtin_LINE``, ``__builtin_FUNCTION``, and ``__builtin_FILE`` return
+the values, at the "invocation point", for ``__LINE__``, ``__FUNCTION__``, and
+``__FILE__`` respectively. These builtins are constant expressions.
+
+When the builtins appear as part of a default function argument the invocation
+point is the location of the caller. When the builtins appear as part of a
+default member initializer, the invocation point is the location of the
+constructor or aggregate initialization used to create the object. Otherwise
+the invocation point is the same as the location of the builtin.
+
+When the invocation point of ``__builtin_FUNCTION`` is not a function scope the
+empty string is returned.
+
Non-standard C++11 Attributes
=============================
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu May 16 14:04:15 2019
@@ -271,6 +271,12 @@ private:
llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *>
MaterializedTemporaryValues;
+ /// A cache mapping a string value to a StringLiteral object with the same
+ /// value.
+ ///
+ /// This is lazily created. This is intentionally not serialized.
+ mutable llvm::StringMap<StringLiteral *> StringLiteralCache;
+
/// Representation of a "canonical" template template parameter that
/// is used in canonical template names.
class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
@@ -1323,6 +1329,10 @@ public:
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals) const;
+ /// Return a type for a constant array for a string literal of the
+ /// specified element type and length.
+ QualType getStringLiteralArrayType(QualType EltTy, unsigned Length) const;
+
/// Returns a vla type where known sizes are replaced with [*].
QualType getVariableArrayDecayedType(QualType Ty) const;
@@ -2805,6 +2815,11 @@ public:
APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E,
bool MayCreate);
+ /// Return a string representing the human readable name for the specified
+ /// function declaration or file name. Used by SourceLocExpr and
+ /// PredefinedExpr to cache evaluated results.
+ StringLiteral *getPredefinedStringLiteralFromCache(StringRef Key) const;
+
//===--------------------------------------------------------------------===//
// Statistics
//===--------------------------------------------------------------------===//
Added: cfe/trunk/include/clang/AST/CurrentSourceLocExprScope.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CurrentSourceLocExprScope.h?rev=360937&view=auto
==============================================================================
--- cfe/trunk/include/clang/AST/CurrentSourceLocExprScope.h (added)
+++ cfe/trunk/include/clang/AST/CurrentSourceLocExprScope.h Thu May 16 14:04:15 2019
@@ -0,0 +1,75 @@
+//===--- CurrentSourceLocExprScope.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines types used to track the current context needed to evaluate
+// a SourceLocExpr.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CURRENT_SOURCE_LOC_EXPR_SCOPE_H
+#define LLVM_CLANG_AST_CURRENT_SOURCE_LOC_EXPR_SCOPE_H
+
+#include <cassert>
+
+namespace clang {
+class Expr;
+
+/// Represents the current source location and context used to determine the
+/// value of the source location builtins (ex. __builtin_LINE), including the
+/// context of default argument and default initializer expressions.
+class CurrentSourceLocExprScope {
+ /// The CXXDefaultArgExpr or CXXDefaultInitExpr we're currently evaluating.
+ const Expr *DefaultExpr = nullptr;
+
+public:
+ /// A RAII style scope guard used for tracking the current source
+ /// location and context as used by the source location builtins
+ /// (ex. __builtin_LINE).
+ class SourceLocExprScopeGuard;
+
+ const Expr *getDefaultExpr() const { return DefaultExpr; }
+
+ explicit CurrentSourceLocExprScope() = default;
+
+private:
+ explicit CurrentSourceLocExprScope(const Expr *DefaultExpr)
+ : DefaultExpr(DefaultExpr) {}
+
+ CurrentSourceLocExprScope(CurrentSourceLocExprScope const &) = default;
+ CurrentSourceLocExprScope &
+ operator=(CurrentSourceLocExprScope const &) = default;
+};
+
+class CurrentSourceLocExprScope::SourceLocExprScopeGuard {
+public:
+ SourceLocExprScopeGuard(const Expr *DefaultExpr,
+ CurrentSourceLocExprScope &Current)
+ : Current(Current), OldVal(Current), Enable(false) {
+ assert(DefaultExpr && "the new scope should not be empty");
+ if ((Enable = (Current.getDefaultExpr() == nullptr)))
+ Current = CurrentSourceLocExprScope(DefaultExpr);
+ }
+
+ ~SourceLocExprScopeGuard() {
+ if (Enable)
+ Current = OldVal;
+ }
+
+private:
+ SourceLocExprScopeGuard(SourceLocExprScopeGuard const &) = delete;
+ SourceLocExprScopeGuard &operator=(SourceLocExprScopeGuard const &) = delete;
+
+ CurrentSourceLocExprScope &Current;
+ CurrentSourceLocExprScope OldVal;
+ bool Enable;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_CURRENT_SOURCE_LOC_EXPR_SCOPE_H
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu May 16 14:04:15 2019
@@ -4171,6 +4171,70 @@ public:
}
};
+/// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(),
+/// __builtin_FUNCTION(), or __builtin_FILE().
+class SourceLocExpr final : public Expr {
+ SourceLocation BuiltinLoc, RParenLoc;
+ DeclContext *ParentContext;
+
+public:
+ enum IdentKind { Function, File, Line, Column };
+
+ SourceLocExpr(const ASTContext &Ctx, IdentKind Type, SourceLocation BLoc,
+ SourceLocation RParenLoc, DeclContext *Context);
+
+ /// Build an empty call expression.
+ explicit SourceLocExpr(EmptyShell Empty) : Expr(SourceLocExprClass, Empty) {}
+
+ /// Return the result of evaluating this SourceLocExpr in the specified
+ /// (and possibly null) default argument or initialization context.
+ APValue EvaluateInContext(const ASTContext &Ctx,
+ const Expr *DefaultExpr) const;
+
+ /// Return a string representing the name of the specific builtin function.
+ StringRef getBuiltinStr() const;
+
+ IdentKind getIdentKind() const {
+ return static_cast<IdentKind>(SourceLocExprBits.Kind);
+ }
+
+ bool isStringType() const {
+ switch (getIdentKind()) {
+ case File:
+ case Function:
+ return true;
+ case Line:
+ case Column:
+ return false;
+ }
+ }
+ bool isIntType() const LLVM_READONLY { return !isStringType(); }
+
+ /// If the SourceLocExpr has been resolved return the subexpression
+ /// representing the resolved value. Otherwise return null.
+ const DeclContext *getParentContext() const { return ParentContext; }
+ DeclContext *getParentContext() { return ParentContext; }
+
+ SourceLocation getLocation() const { return BuiltinLoc; }
+ SourceLocation getBeginLoc() const { return BuiltinLoc; }
+ SourceLocation getEndLoc() const { return RParenLoc; }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ const_child_range children() const {
+ return const_child_range(child_iterator(), child_iterator());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SourceLocExprClass;
+ }
+
+private:
+ friend class ASTStmtReader;
+};
+
/// Describes an C or C++ initializer list.
///
/// InitListExpr describes an initializer list, which can be used to
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Thu May 16 14:04:15 2019
@@ -1121,7 +1121,11 @@ class CXXDefaultArgExpr final : public E
/// The parameter whose default is being used.
ParmVarDecl *Param;
- CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param)
+ /// The context where the default argument expression was used.
+ DeclContext *UsedContext;
+
+ CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param,
+ DeclContext *UsedContext)
: Expr(SC,
Param->hasUnparsedDefaultArg()
? Param->getType().getNonReferenceType()
@@ -1129,7 +1133,7 @@ class CXXDefaultArgExpr final : public E
Param->getDefaultArg()->getValueKind(),
Param->getDefaultArg()->getObjectKind(), false, false, false,
false),
- Param(Param) {
+ Param(Param), UsedContext(UsedContext) {
CXXDefaultArgExprBits.Loc = Loc;
}
@@ -1139,8 +1143,10 @@ public:
// \p Param is the parameter whose default argument is used by this
// expression.
static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
- ParmVarDecl *Param) {
- return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param);
+ ParmVarDecl *Param,
+ DeclContext *UsedContext) {
+ return new (C)
+ CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, UsedContext);
}
// Retrieve the parameter that the argument was created from.
@@ -1151,6 +1157,9 @@ public:
const Expr *getExpr() const { return getParam()->getDefaultArg(); }
Expr *getExpr() { return getParam()->getDefaultArg(); }
+ const DeclContext *getUsedContext() const { return UsedContext; }
+ DeclContext *getUsedContext() { return UsedContext; }
+
/// Retrieve the location where this default argument was actually used.
SourceLocation getUsedLocation() const { return CXXDefaultArgExprBits.Loc; }
@@ -1190,8 +1199,11 @@ class CXXDefaultInitExpr : public Expr {
/// The field whose default is being used.
FieldDecl *Field;
+ /// The context where the default initializer expression was used.
+ DeclContext *UsedContext;
+
CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
- FieldDecl *Field, QualType Ty);
+ FieldDecl *Field, QualType Ty, DeclContext *UsedContext);
CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {}
@@ -1199,8 +1211,8 @@ public:
/// \p Field is the non-static data member whose default initializer is used
/// by this expression.
static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc,
- FieldDecl *Field) {
- return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType());
+ FieldDecl *Field, DeclContext *UsedContext) {
+ return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType(), UsedContext);
}
/// Get the field whose initializer will be used.
@@ -1217,6 +1229,13 @@ public:
return Field->getInClassInitializer();
}
+ const DeclContext *getUsedContext() const { return UsedContext; }
+ DeclContext *getUsedContext() { return UsedContext; }
+
+ /// Retrieve the location where this default initializer expression was
+ /// actually used.
+ SourceLocation getUsedLocation() const { return getBeginLoc(); }
+
SourceLocation getBeginLoc() const { return CXXDefaultInitExprBits.Loc; }
SourceLocation getEndLoc() const { return CXXDefaultInitExprBits.Loc; }
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Thu May 16 14:04:15 2019
@@ -2550,6 +2550,8 @@ DEF_TRAVERSE_STMT(PredefinedExpr, {})
DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
DEF_TRAVERSE_STMT(StmtExpr, {})
+DEF_TRAVERSE_STMT(SourceLocExpr, {})
+
DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
if (S->hasExplicitTemplateArgs()) {
Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Thu May 16 14:04:15 2019
@@ -550,6 +550,17 @@ protected:
unsigned ResultIndex : 32 - 8 - NumExprBits;
};
+ class SourceLocExprBitfields {
+ friend class ASTStmtReader;
+ friend class SourceLocExpr;
+
+ unsigned : NumExprBits;
+
+ /// The kind of source location builtin represented by the SourceLocExpr.
+ /// Ex. __builtin_LINE, __builtin_FUNCTION, ect.
+ unsigned Kind : 2;
+ };
+
//===--- C++ Expression bitfields classes ---===//
class CXXOperatorCallExprBitfields {
@@ -935,6 +946,7 @@ protected:
ParenListExprBitfields ParenListExprBits;
GenericSelectionExprBitfields GenericSelectionExprBits;
PseudoObjectExprBitfields PseudoObjectExprBits;
+ SourceLocExprBitfields SourceLocExprBits;
// C++ Expressions
CXXOperatorCallExprBitfields CXXOperatorCallExprBits;
Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Thu May 16 14:04:15 2019
@@ -96,6 +96,7 @@ def ParenListExpr : DStmt<Expr>;
def VAArgExpr : DStmt<Expr>;
def GenericSelectionExpr : DStmt<Expr>;
def PseudoObjectExpr : DStmt<Expr>;
+def SourceLocExpr : DStmt<Expr>;
// Wrapper expressions
def FullExpr : DStmt<Expr, 1>;
Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu May 16 14:04:15 2019
@@ -404,6 +404,11 @@ KEYWORD(__alignof , KE
KEYWORD(__attribute , KEYALL)
KEYWORD(__builtin_choose_expr , KEYALL)
KEYWORD(__builtin_offsetof , KEYALL)
+KEYWORD(__builtin_FILE , KEYALL)
+KEYWORD(__builtin_FUNCTION , KEYALL)
+KEYWORD(__builtin_LINE , KEYALL)
+KEYWORD(__builtin_COLUMN , KEYALL)
+
// __builtin_types_compatible_p is a GNU C extension that we handle like a C++
// type trait.
TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX)
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu May 16 14:04:15 2019
@@ -4612,6 +4612,21 @@ public:
ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
TypeSourceInfo *TInfo, SourceLocation RPLoc);
+ // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FILE(),
+ // __builtin_COLUMN()
+ ExprResult ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind,
+ SourceLocation BuiltinLoc,
+ SourceLocation RPLoc);
+
+ /// Build a potentially resolved SourceLocExpr.
+ ///
+ /// \param SubExpr - null when the SourceLocExpr is unresolved, otherwise
+ /// SubExpr will be a literal expression representing the value of the
+ /// builtin call.
+ ExprResult BuildSourceLocExpr(SourceLocExpr::IdentKind Kind,
+ SourceLocation BuiltinLoc, SourceLocation RPLoc,
+ DeclContext *ParentContext);
+
// __null
ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu May 16 14:04:15 2019
@@ -1732,6 +1732,9 @@ namespace serialization {
/// A GNUNullExpr record.
EXPR_GNU_NULL,
+ /// A SourceLocExpr record.
+ EXPR_SOURCE_LOC,
+
/// A ShuffleVectorExpr record.
EXPR_SHUFFLE_VECTOR,
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu May 16 14:04:15 2019
@@ -10208,6 +10208,31 @@ ASTContext::getMaterializedTemporaryValu
return MaterializedTemporaryValues.lookup(E);
}
+QualType ASTContext::getStringLiteralArrayType(QualType EltTy,
+ unsigned Length) const {
+ // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
+ if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
+ EltTy = EltTy.withConst();
+
+ EltTy = adjustStringLiteralBaseType(EltTy);
+
+ // Get an array type for the string, according to C99 6.4.5. This includes
+ // the null terminator character.
+ return getConstantArrayType(EltTy, llvm::APInt(32, Length + 1),
+ ArrayType::Normal, /*IndexTypeQuals*/ 0);
+}
+
+StringLiteral *
+ASTContext::getPredefinedStringLiteralFromCache(StringRef Key) const {
+ StringLiteral *&Result = StringLiteralCache[Key];
+ if (!Result)
+ Result = StringLiteral::Create(
+ *this, Key, StringLiteral::Ascii,
+ /*Pascal*/ false, getStringLiteralArrayType(CharTy, Key.size()),
+ SourceLocation());
+ return Result;
+}
+
bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
const llvm::Triple &T = getTargetInfo().getTriple();
if (!T.isOSDarwin())
Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu May 16 14:04:15 2019
@@ -6801,8 +6801,12 @@ ExpectedStmt ASTNodeImporter::VisitCXXDe
if (!ToParamOrErr)
return ToParamOrErr.takeError();
+ auto UsedContextOrErr = Importer.ImportContext(E->getUsedContext());
+ if (!UsedContextOrErr)
+ return UsedContextOrErr.takeError();
+
return CXXDefaultArgExpr::Create(
- Importer.getToContext(), *ToUsedLocOrErr, *ToParamOrErr);
+ Importer.getToContext(), *ToUsedLocOrErr, *ToParamOrErr, *UsedContextOrErr);
}
ExpectedStmt
@@ -7525,8 +7529,12 @@ ExpectedStmt ASTNodeImporter::VisitCXXDe
if (!ToFieldOrErr)
return ToFieldOrErr.takeError();
+ auto UsedContextOrErr = Importer.ImportContext(E->getUsedContext());
+ if (!UsedContextOrErr)
+ return UsedContextOrErr.takeError();
+
return CXXDefaultInitExpr::Create(
- Importer.getToContext(), *ToBeginLocOrErr, *ToFieldOrErr);
+ Importer.getToContext(), *ToBeginLocOrErr, *ToFieldOrErr, *UsedContextOrErr);
}
ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu May 16 14:04:15 2019
@@ -10,13 +10,14 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/Expr.h"
+#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
-#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
@@ -1992,6 +1993,91 @@ bool BinaryOperator::isNullPointerArithm
return true;
}
+
+static QualType getDecayedSourceLocExprType(const ASTContext &Ctx,
+ SourceLocExpr::IdentKind Kind) {
+ switch (Kind) {
+ case SourceLocExpr::File:
+ case SourceLocExpr::Function: {
+ QualType ArrTy = Ctx.getStringLiteralArrayType(Ctx.CharTy, 0);
+ return Ctx.getPointerType(ArrTy->getAsArrayTypeUnsafe()->getElementType());
+ }
+ case SourceLocExpr::Line:
+ case SourceLocExpr::Column:
+ return Ctx.UnsignedIntTy;
+ }
+ llvm_unreachable("unhandled case");
+}
+
+SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, IdentKind Kind,
+ SourceLocation BLoc, SourceLocation RParenLoc,
+ DeclContext *ParentContext)
+ : Expr(SourceLocExprClass, getDecayedSourceLocExprType(Ctx, Kind),
+ VK_RValue, OK_Ordinary, false, false, false, false),
+ BuiltinLoc(BLoc), RParenLoc(RParenLoc), ParentContext(ParentContext) {
+ SourceLocExprBits.Kind = Kind;
+}
+
+StringRef SourceLocExpr::getBuiltinStr() const {
+ switch (getIdentKind()) {
+ case File:
+ return "__builtin_FILE";
+ case Function:
+ return "__builtin_FUNCTION";
+ case Line:
+ return "__builtin_LINE";
+ case Column:
+ return "__builtin_COLUMN";
+ }
+ llvm_unreachable("unexpected IdentKind!");
+}
+
+APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx,
+ const Expr *DefaultExpr) const {
+ SourceLocation Loc;
+ const DeclContext *Context;
+
+ std::tie(Loc,
+ Context) = [&]() -> std::pair<SourceLocation, const DeclContext *> {
+ if (auto *DIE = dyn_cast_or_null<CXXDefaultInitExpr>(DefaultExpr))
+ return {DIE->getUsedLocation(), DIE->getUsedContext()};
+ if (auto *DAE = dyn_cast_or_null<CXXDefaultArgExpr>(DefaultExpr))
+ return {DAE->getUsedLocation(), DAE->getUsedContext()};
+ return {this->getLocation(), this->getParentContext()};
+ }();
+
+ PresumedLoc PLoc = Ctx.getSourceManager().getPresumedLoc(
+ Ctx.getSourceManager().getExpansionRange(Loc).getEnd());
+
+ auto MakeStringLiteral = [&](StringRef Tmp) {
+ using LValuePathEntry = APValue::LValuePathEntry;
+ StringLiteral *Res = Ctx.getPredefinedStringLiteralFromCache(Tmp);
+ // Decay the string to a pointer to the first character.
+ LValuePathEntry Path[1] = {LValuePathEntry::ArrayIndex(0)};
+ return APValue(Res, CharUnits::Zero(), Path, /*OnePastTheEnd=*/false);
+ };
+
+ switch (getIdentKind()) {
+ case SourceLocExpr::File:
+ return MakeStringLiteral(PLoc.getFilename());
+ case SourceLocExpr::Function: {
+ const Decl *CurDecl = dyn_cast_or_null<Decl>(Context);
+ return MakeStringLiteral(
+ CurDecl ? PredefinedExpr::ComputeName(PredefinedExpr::Function, CurDecl)
+ : std::string(""));
+ }
+ case SourceLocExpr::Line:
+ case SourceLocExpr::Column: {
+ llvm::APSInt IntVal(Ctx.getIntWidth(Ctx.UnsignedIntTy),
+ /*IsUnsigned=*/true);
+ IntVal = getIdentKind() == SourceLocExpr::Line ? PLoc.getLine()
+ : PLoc.getColumn();
+ return APValue(IntVal);
+ }
+ }
+ llvm_unreachable("unhandled case");
+}
+
InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
ArrayRef<Expr*> initExprs, SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
@@ -3156,6 +3242,7 @@ bool Expr::HasSideEffects(const ASTConte
case ObjCAvailabilityCheckExprClass:
case CXXUuidofExprClass:
case OpaqueValueExprClass:
+ case SourceLocExprClass:
// These never have a side-effect.
return false;
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Thu May 16 14:04:15 2019
@@ -907,13 +907,14 @@ const IdentifierInfo *UserDefinedLiteral
}
CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
- FieldDecl *Field, QualType Ty)
+ FieldDecl *Field, QualType Ty,
+ DeclContext *UsedContext)
: Expr(CXXDefaultInitExprClass, Ty.getNonLValueExprType(Ctx),
Ty->isLValueReferenceType() ? VK_LValue : Ty->isRValueReferenceType()
? VK_XValue
: VK_RValue,
/*FIXME*/ OK_Ordinary, false, false, false, false),
- Field(Field) {
+ Field(Field), UsedContext(UsedContext) {
CXXDefaultInitExprBits.Loc = Loc;
assert(Field->hasInClassInitializer());
}
Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Thu May 16 14:04:15 2019
@@ -191,6 +191,7 @@ static Cl::Kinds ClassifyInternal(ASTCon
case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
+ case Expr::SourceLocExprClass:
return Cl::CL_PRValue;
case Expr::ConstantExprClass:
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu May 16 14:04:15 2019
@@ -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 CXXRe
/// 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 handleLValueToRValueConversi
// 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 *
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, c
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:
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu May 16 14:04:15 2019
@@ -3589,6 +3589,7 @@ recurse:
case Expr::AsTypeExprClass:
case Expr::PseudoObjectExprClass:
case Expr::AtomicExprClass:
+ case Expr::SourceLocExprClass:
case Expr::FixedPointLiteralClass:
{
if (!NullOut) {
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Thu May 16 14:04:15 2019
@@ -905,6 +905,10 @@ void StmtPrinter::VisitOMPTargetTeamsDis
// Expr printing methods.
//===----------------------------------------------------------------------===//
+void StmtPrinter::VisitSourceLocExpr(SourceLocExpr *Node) {
+ OS << Node->getBuiltinStr() << "()";
+}
+
void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
PrintExpr(Node->getSubExpr());
}
Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Thu May 16 14:04:15 2019
@@ -1882,6 +1882,10 @@ void StmtProfiler::VisitTypoExpr(const T
VisitExpr(E);
}
+void StmtProfiler::VisitSourceLocExpr(const SourceLocExpr *E) {
+ VisitExpr(E);
+}
+
void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) {
VisitExpr(S);
}
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu May 16 14:04:15 2019
@@ -1315,11 +1315,15 @@ LValue CodeGenFunction::EmitLValue(const
return LV;
}
- case Expr::CXXDefaultArgExprClass:
- return EmitLValue(cast<CXXDefaultArgExpr>(E)->getExpr());
+ case Expr::CXXDefaultArgExprClass: {
+ auto *DAE = cast<CXXDefaultArgExpr>(E);
+ CXXDefaultArgExprScope Scope(*this, DAE);
+ return EmitLValue(DAE->getExpr());
+ }
case Expr::CXXDefaultInitExprClass: {
- CXXDefaultInitExprScope Scope(*this);
- return EmitLValue(cast<CXXDefaultInitExpr>(E)->getExpr());
+ auto *DIE = cast<CXXDefaultInitExpr>(E);
+ CXXDefaultInitExprScope Scope(*this, DIE);
+ return EmitLValue(DIE->getExpr());
}
case Expr::CXXTypeidExprClass:
return EmitCXXTypeidLValue(cast<CXXTypeidExpr>(E));
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu May 16 14:04:15 2019
@@ -165,10 +165,11 @@ public:
void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing.
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ CodeGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE);
Visit(DAE->getExpr());
}
void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
- CodeGenFunction::CXXDefaultInitExprScope Scope(CGF);
+ CodeGenFunction::CXXDefaultInitExprScope Scope(CGF, DIE);
Visit(DIE->getExpr());
}
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Thu May 16 14:04:15 2019
@@ -213,10 +213,11 @@ public:
return Visit(E->getSubExpr());
}
ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ CodeGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE);
return Visit(DAE->getExpr());
}
ComplexPairTy VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
- CodeGenFunction::CXXDefaultInitExprScope Scope(CGF);
+ CodeGenFunction::CXXDefaultInitExprScope Scope(CGF, DIE);
return Visit(DIE->getExpr());
}
ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu May 16 14:04:15 2019
@@ -884,10 +884,6 @@ public:
llvm_unreachable("Invalid CastKind");
}
- llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE, QualType T) {
- return Visit(DAE->getExpr(), T);
- }
-
llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE, QualType T) {
// No need for a DefaultInitExprScope: we don't handle 'this' in a
// constant expression.
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu May 16 14:04:15 2019
@@ -16,6 +16,7 @@
#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -640,12 +641,20 @@ public:
Value *VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E) {
return EmitLoadOfLValue(E);
}
+ Value *VisitSourceLocExpr(SourceLocExpr *SLE) {
+ auto &Ctx = CGF.getContext();
+ APValue Evaluated =
+ SLE->EvaluateInContext(Ctx, CGF.CurSourceLocExprScope.getDefaultExpr());
+ return ConstantEmitter(CGF.CGM, &CGF)
+ .emitAbstract(SLE->getLocation(), Evaluated, SLE->getType());
+ }
Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ CodeGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE);
return Visit(DAE->getExpr());
}
Value *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
- CodeGenFunction::CXXDefaultInitExprScope Scope(CGF);
+ CodeGenFunction::CXXDefaultInitExprScope Scope(CGF, DIE);
return Visit(DIE->getExpr());
}
Value *VisitCXXThisExpr(CXXThisExpr *TE) {
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu May 16 14:04:15 2019
@@ -22,6 +22,7 @@
#include "EHScopeStack.h"
#include "VarBypassDetector.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/CurrentSourceLocExprScope.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
@@ -1393,6 +1394,12 @@ private:
SourceLocation LastStopPoint;
public:
+ /// Source location information about the default argument or member
+ /// initializer expression we're evaluating, if any.
+ CurrentSourceLocExprScope CurSourceLocExprScope;
+ using SourceLocExprScopeGuard =
+ CurrentSourceLocExprScope::SourceLocExprScopeGuard;
+
/// A scope within which we are constructing the fields of an object which
/// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use
/// if we need to evaluate a CXXDefaultInitExpr within the evaluation.
@@ -1413,11 +1420,12 @@ public:
/// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
/// is overridden to be the object under construction.
- class CXXDefaultInitExprScope {
+ class CXXDefaultInitExprScope {
public:
- CXXDefaultInitExprScope(CodeGenFunction &CGF)
- : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue),
- OldCXXThisAlignment(CGF.CXXThisAlignment) {
+ CXXDefaultInitExprScope(CodeGenFunction &CGF, const CXXDefaultInitExpr *E)
+ : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue),
+ OldCXXThisAlignment(CGF.CXXThisAlignment),
+ SourceLocScope(E, CGF.CurSourceLocExprScope) {
CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer();
CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment();
}
@@ -1430,6 +1438,12 @@ public:
CodeGenFunction &CGF;
llvm::Value *OldCXXThisValue;
CharUnits OldCXXThisAlignment;
+ SourceLocExprScopeGuard SourceLocScope;
+ };
+
+ struct CXXDefaultArgExprScope : SourceLocExprScopeGuard {
+ CXXDefaultArgExprScope(CodeGenFunction &CGF, const CXXDefaultArgExpr *E)
+ : SourceLocExprScopeGuard(E, CGF.CurSourceLocExprScope) {}
};
/// The scope of an ArrayInitLoopExpr. Within this scope, the value of the
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu May 16 14:04:15 2019
@@ -639,6 +639,10 @@ class CastExpressionIdValidator final :
/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
/// assign-expr ')'
+/// [GNU] '__builtin_FILE' '(' ')'
+/// [GNU] '__builtin_FUNCTION' '(' ')'
+/// [GNU] '__builtin_LINE' '(' ')'
+/// [CLANG] '__builtin_COLUMN' '(' ')'
/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
/// [GNU] '__null'
/// [OBJC] '[' objc-message-expr ']'
@@ -1106,6 +1110,10 @@ ExprResult Parser::ParseCastExpression(b
case tok::kw___builtin_choose_expr:
case tok::kw___builtin_astype: // primary-expression: [OCL] as_type()
case tok::kw___builtin_convertvector:
+ case tok::kw___builtin_COLUMN:
+ case tok::kw___builtin_FILE:
+ case tok::kw___builtin_FUNCTION:
+ case tok::kw___builtin_LINE:
return ParseBuiltinPrimaryExpression();
case tok::kw___null:
return Actions.ActOnGNUNullExpr(ConsumeToken());
@@ -2067,6 +2075,10 @@ ExprResult Parser::ParseUnaryExprOrTypeT
/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
/// assign-expr ')'
/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
+/// [GNU] '__builtin_FILE' '(' ')'
+/// [GNU] '__builtin_FUNCTION' '(' ')'
+/// [GNU] '__builtin_LINE' '(' ')'
+/// [CLANG] '__builtin_COLUMN' '(' ')'
/// [OCL] '__builtin_astype' '(' assignment-expression ',' type-name ')'
///
/// [GNU] offsetof-member-designator:
@@ -2286,6 +2298,33 @@ ExprResult Parser::ParseBuiltinPrimaryEx
ConsumeParen());
break;
}
+ case tok::kw___builtin_COLUMN:
+ case tok::kw___builtin_FILE:
+ case tok::kw___builtin_FUNCTION:
+ case tok::kw___builtin_LINE: {
+ // Attempt to consume the r-paren.
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected) << tok::r_paren;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return ExprError();
+ }
+ SourceLocExpr::IdentKind Kind = [&] {
+ switch (T) {
+ case tok::kw___builtin_FILE:
+ return SourceLocExpr::File;
+ case tok::kw___builtin_FUNCTION:
+ return SourceLocExpr::Function;
+ case tok::kw___builtin_LINE:
+ return SourceLocExpr::Line;
+ case tok::kw___builtin_COLUMN:
+ return SourceLocExpr::Column;
+ default:
+ llvm_unreachable("invalid keyword");
+ }
+ }();
+ Res = Actions.ActOnSourceLocExpr(Kind, StartLoc, ConsumeParen());
+ break;
+ }
}
if (Res.isInvalid())
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu May 16 14:04:15 2019
@@ -62,7 +62,7 @@ namespace {
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 @@ ExprResult Sema::BuildCXXDefaultInitExpr
// 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 @@ ExprResult Sema::BuildCXXDefaultInitExpr
Field->setInvalidDecl();
return ExprError();
}
- return CXXDefaultInitExpr::Create(Context, Loc, Field);
+ return CXXDefaultInitExpr::Create(Context, Loc, Field, CurContext);
}
// DR1351:
Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Thu May 16 14:04:15 2019
@@ -1289,6 +1289,7 @@ CanThrowResult Sema::canThrow(const Expr
case Expr::PredefinedExprClass:
case Expr::SizeOfPackExprClass:
case Expr::StringLiteralClass:
+ case Expr::SourceLocExprClass:
// These expressions can never throw.
return CT_Cannot;
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu May 16 14:04:15 2019
@@ -1683,20 +1683,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token>
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 @@ ExprResult Sema::BuildCXXDefaultArgExpr(
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 @@ bool Sema::GatherArgumentsForCall(Source
} 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 @@ ExprResult Sema::ActOnGNUNullExpr(Source
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)
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Thu May 16 14:04:15 2019
@@ -1097,12 +1097,7 @@ ExprResult Sema::BuildObjCEncodeExpressi
// 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);
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu May 16 14:04:15 2019
@@ -2713,9 +2713,9 @@ public:
/// 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 @@ public:
/// 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 @@ public:
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 @@ TreeTransform<Derived>::TransformCXXMemb
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 @@ TreeTransform<Derived>::TransformCXXDefa
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 @@ TreeTransform<Derived>::TransformCXXDefa
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);
Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Thu May 16 14:04:15 2019
@@ -968,6 +968,15 @@ void ASTStmtReader::VisitVAArgExpr(VAArg
E->setIsMicrosoftABI(Record.readInt());
}
+void ASTStmtReader::VisitSourceLocExpr(SourceLocExpr *E) {
+ VisitExpr(E);
+ E->ParentContext = ReadDeclAs<DeclContext>();
+ E->BuiltinLoc = ReadSourceLocation();
+ E->RParenLoc = ReadSourceLocation();
+ E->SourceLocExprBits.Kind =
+ static_cast<SourceLocExpr::IdentKind>(Record.readInt());
+}
+
void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
VisitExpr(E);
E->setAmpAmpLoc(ReadSourceLocation());
@@ -1487,12 +1496,14 @@ void ASTStmtReader::VisitCXXThrowExpr(CX
void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
VisitExpr(E);
E->Param = ReadDeclAs<ParmVarDecl>();
+ E->UsedContext = ReadDeclAs<DeclContext>();
E->CXXDefaultArgExprBits.Loc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
VisitExpr(E);
E->Field = ReadDeclAs<FieldDecl>();
+ E->UsedContext = ReadDeclAs<DeclContext>();
E->CXXDefaultInitExprBits.Loc = ReadSourceLocation();
}
@@ -2651,6 +2662,10 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
S = new (Context) VAArgExpr(Empty);
break;
+ case EXPR_SOURCE_LOC:
+ S = new (Context) SourceLocExpr(Empty);
+ break;
+
case EXPR_ADDR_LABEL:
S = new (Context) AddrLabelExpr(Empty);
break;
Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Thu May 16 14:04:15 2019
@@ -909,6 +909,15 @@ void ASTStmtWriter::VisitVAArgExpr(VAArg
Code = serialization::EXPR_VA_ARG;
}
+void ASTStmtWriter::VisitSourceLocExpr(SourceLocExpr *E) {
+ VisitExpr(E);
+ Record.AddDeclRef(cast_or_null<Decl>(E->getParentContext()));
+ Record.AddSourceLocation(E->getBeginLoc());
+ Record.AddSourceLocation(E->getEndLoc());
+ Record.push_back(E->getIdentKind());
+ Code = serialization::EXPR_SOURCE_LOC;
+}
+
void ASTStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
VisitExpr(E);
Record.AddSourceLocation(E->getAmpAmpLoc());
@@ -1468,6 +1477,7 @@ void ASTStmtWriter::VisitCXXThrowExpr(CX
void ASTStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
VisitExpr(E);
Record.AddDeclRef(E->getParam());
+ Record.AddDeclRef(cast_or_null<Decl>(E->getUsedContext()));
Record.AddSourceLocation(E->getUsedLocation());
Code = serialization::EXPR_CXX_DEFAULT_ARG;
}
@@ -1475,6 +1485,7 @@ void ASTStmtWriter::VisitCXXDefaultArgEx
void ASTStmtWriter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
VisitExpr(E);
Record.AddDeclRef(E->getField());
+ Record.AddDeclRef(cast_or_null<Decl>(E->getUsedContext()));
Record.AddSourceLocation(E->getExprLoc());
Code = serialization::EXPR_CXX_DEFAULT_INIT;
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Thu May 16 14:04:15 2019
@@ -1341,6 +1341,7 @@ void ExprEngine::Visit(const Stmt *S, Ex
case Stmt::NoInitExprClass:
case Stmt::SizeOfPackExprClass:
case Stmt::StringLiteralClass:
+ case Stmt::SourceLocExprClass:
case Stmt::ObjCStringLiteralClass:
case Stmt::CXXPseudoDestructorExprClass:
case Stmt::SubstNonTypeTemplateParmExprClass:
Added: cfe/trunk/test/CodeGenCXX/builtin-source-location.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/builtin-source-location.cpp?rev=360937&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/builtin-source-location.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/builtin-source-location.cpp Thu May 16 14:04:15 2019
@@ -0,0 +1,268 @@
+// RUN: %clang_cc1 -std=c++2a -fblocks %s -triple %itanium_abi_triple -emit-llvm -o %t.ll
+
+#line 8 "builtin-source-location.cpp"
+
+struct source_location {
+private:
+ unsigned int __m_line = 0;
+ unsigned int __m_col = 0;
+ const char *__m_file = nullptr;
+ const char *__m_func = nullptr;
+
+public:
+ constexpr void set(unsigned l, unsigned c, const char *f, const char *func) {
+ __m_line = l;
+ __m_col = c;
+ __m_file = f;
+ __m_func = func;
+ }
+ static constexpr source_location current(
+ unsigned int __line = __builtin_LINE(),
+ unsigned int __col = __builtin_COLUMN(),
+ const char *__file = __builtin_FILE(),
+ const char *__func = __builtin_FUNCTION()) noexcept {
+ source_location __loc;
+ __loc.set(__line, __col, __file, __func);
+ return __loc;
+ }
+ static source_location bad_current(
+ unsigned int __line = __builtin_LINE(),
+ unsigned int __col = __builtin_COLUMN(),
+ const char *__file = __builtin_FILE(),
+ const char *__func = __builtin_FUNCTION()) noexcept {
+ source_location __loc;
+ __loc.set(__line, __col, __file, __func);
+ return __loc;
+ }
+ constexpr source_location() = default;
+ constexpr source_location(source_location const &) = default;
+ constexpr unsigned int line() const noexcept { return __m_line; }
+ constexpr unsigned int column() const noexcept { return __m_col; }
+ constexpr const char *file() const noexcept { return __m_file; }
+ constexpr const char *function() const noexcept { return __m_func; }
+};
+
+using SL = source_location;
+
+extern "C" int sink(...);
+
+
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-GLOBAL-ONE
+//
+// CHECK-GLOBAL-ONE-DAG: @[[FILE:.*]] = {{.*}}c"test_const_init.cpp\00"
+// CHECK-GLOBAL-ONE-DAG: @[[FUNC:.*]] = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+//
+// CHECK-GLOBAL-ONE: @const_init_global = global %struct.source_location { i32 1000, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
+#line 1000 "test_const_init.cpp"
+SL const_init_global = SL::current();
+
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-GLOBAL-TWO
+//
+// CHECK-GLOBAL-TWO-DAG: @runtime_init_global = global %struct.source_location zeroinitializer, align 8
+//
+// CHECK-GLOBAL-TWO-DAG: @[[FILE:.*]] = {{.*}}c"test_runtime_init.cpp\00"
+// CHECK-GLOBAL-TWO-DAG: @[[FUNC:.*]] = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+//
+// CHECK-GLOBAL-TWO: define internal void @__cxx_global_var_init()
+// CHECK-GLOBAL-TWO-NOT: ret
+// CHECK-GLOBAL-TWO: call void @_ZN15source_location11bad_currentEjjPKcS1_(%struct.source_location* sret @runtime_init_global,
+// CHECK-GLOBAL-TWO-SAME: i32 1100, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]],
+#line 1100 "test_runtime_init.cpp"
+SL runtime_init_global = SL::bad_current();
+
+#line 2000 "test_function.cpp"
+extern "C" void test_function() {
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-LOCAL-ONE
+//
+// CHECK-LOCAL-ONE-DAG: @[[FILE:.*]] = {{.*}}c"test_current.cpp\00"
+// CHECK-LOCAL-ONE-DAG: @[[FUNC:.*]] = {{.*}}c"test_function\00"
+//
+// CHECK-LOCAL-ONE: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %local,
+// CHECK-LOCAL-ONE-SAME: i32 2100, i32 {{[0-9]+}},
+// CHECK-LOCAL-ONE-SAME: {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]],
+#line 2100 "test_current.cpp"
+ SL local = SL::current();
+}
+
+#line 3000 "TestInitClass.cpp"
+struct TestInit {
+ SL info = SL::current();
+ SL arg_info;
+
+#line 3100 "TestInitCtor.cpp"
+ TestInit(SL arg_info = SL::current()) : arg_info(arg_info) {}
+};
+
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-CTOR-GLOBAL
+//
+// CHECK-CTOR-GLOBAL-DAG: @GlobalInitVal = global %struct.TestInit zeroinitializer, align 8
+// CHECK-CTOR-GLOBAL-DAG: @[[FILE:.*]] = {{.*}}c"GlobalInitVal.cpp\00"
+// CHECK-CTOR-GLOBAL-DAG: @[[FUNC:.*]] = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+//
+// CHECK-CTOR-GLOBAL: define internal void @__cxx_global_var_init.{{[0-9]+}}()
+// CHECK-CTOR-GLOBAL-NOT: ret
+//
+// CHECK-CTOR-GLOBAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %[[TMP_ONE:[^,]*]],
+// CHECK-CTOR-GLOBAL-SAME: i32 3400, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]],
+// CHECK-CTOR-GLOBAL-NEXT: call void @_ZN8TestInitC1E15source_location(%struct.TestInit* @GlobalInitVal, %struct.source_location* {{[^%]*}}%[[TMP_ONE]])
+#line 3400 "GlobalInitVal.cpp"
+TestInit GlobalInitVal;
+
+extern "C" void test_init_function() {
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-CTOR-LOCAL
+//
+// CHECK-CTOR-LOCAL-DAG: @[[FILE:.*]] = {{.*}}c"LocalInitVal.cpp\00"
+// CHECK-CTOR-LOCAL-DAG: @[[FUNC:.*]] = {{.*}}c"test_init_function\00"
+//
+// CHECK-CTOR-LOCAL: define void @test_init_function()
+// CHECK-CTOR-LOCAL-NOT: ret
+//
+// CHECK-CTOR-LOCAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %[[TMP:[^,]*]],
+// CHECK-CTOR-LOCAL-SAME: i32 3500, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]],
+// CHECK-CTOR-LOCAL-NEXT: call void @_ZN8TestInitC1E15source_location(%struct.TestInit* %init_local, %struct.source_location* {{[^%]*}}%[[TMP]])
+#line 3500 "LocalInitVal.cpp"
+ TestInit init_local;
+ sink(init_local);
+}
+
+#line 4000 "ConstexprClass.cpp"
+struct TestInitConstexpr {
+ SL info = SL::current();
+ SL arg_info;
+#line 4200 "ConstexprCtor.cpp"
+ constexpr TestInitConstexpr(SL arg_info = SL::current()) : arg_info(arg_info) {}
+};
+
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-CONSTEXPR-T2
+//
+// CHECK-CONSTEXPR-T2-DAG: @[[FILE_INIT:.*]] = {{.*}}c"ConstexprCtor.cpp\00"
+// CHECK-CONSTEXPR-T2-DAG: @[[FUNC_INIT:.*]] = {{.*}}c"TestInitConstexpr\00"
+// CHECK-CONSTEXPR-T2-DAG: @[[FILE_ARG:.*]] = {{.*}}c"ConstexprGlobal.cpp\00"
+// CHECK-CONSTEXPR-T2-DAG: @[[EMPTY:.*]] = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+//
+// CHECK-CONSTEXPR-T2: @ConstexprGlobal = global %struct.TestInitConstexpr {
+// CHECK-CONSTEXPR-T2-SAME: %struct.source_location { i32 4200, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE_INIT]], {{[^@]*}}@[[FUNC_INIT]],
+// CHECK-CONSTEXPR-T2-SAME: {{[^%]*}}%struct.source_location { i32 4400, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE_ARG]], {{[^@]*}}@[[EMPTY]]
+#line 4400 "ConstexprGlobal.cpp"
+TestInitConstexpr ConstexprGlobal;
+
+extern "C" void test_init_function_constexpr() {
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-CONSTEXPR-LOCAL
+//
+// CHECK-CONSTEXPR-LOCAL-DAG: @[[FUNC:.*]] = {{.*}}c"test_init_function_constexpr\00"
+// CHECK-CONSTEXPR-LOCAL-DAG: @[[FILE:.*]] = {{.*}}c"ConstexprLocal.cpp\00"
+//
+// CHECK-CONSTEXPR-LOCAL: define void @test_init_function_constexpr()
+// CHECK-CONSTEXPR-LOCAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %[[TMP:[^,]*]],
+// CHECK-CONSTEXPR-LOCAL-SAME: i32 4600, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
+// CHECK-CONSTEXPR-LOCAL: call void @_ZN17TestInitConstexprC1E15source_location(%struct.TestInitConstexpr* %local_val, {{.*}}%[[TMP]])
+#line 4600 "ConstexprLocal.cpp"
+ TestInitConstexpr local_val;
+}
+
+#line 5000 "TestInitAgg.cpp"
+struct TestInitAgg {
+#line 5100 "i1.cpp"
+ SL i1;
+#line 5200 "i2.cpp"
+ SL i2 = SL::current();
+#line 5300 "TestInitAggEnd.cpp"
+};
+
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-AGG-DEFAULT
+//
+// CHECK-AGG-DEFAULT-DAG: @[[FILE:.*]] = {{.*}}c"TestInitAgg.cpp\00"
+// CHECK-AGG-DEFAULT-DAG: @[[FUNC:.*]] = {{.*}}c"TestInitAgg\00"
+//
+// CHECK-AGG-DEFAULT: @GlobalAggDefault = global %struct.TestInitAgg {
+// CHECK-AGG-DEFAULT-SAME: %struct.source_location zeroinitializer,
+// CHECK-AGG-DEFAULT-SAME: %struct.source_location { i32 5000, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
+#line 5400 "GlobalAggDefault.cpp"
+TestInitAgg GlobalAggDefault;
+
+#line 5500 "test_agg_init_test.cpp"
+extern "C" void test_agg_init() {
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-AGG-BRACE
+//
+// CHECK-AGG-BRACE-DAG: @[[FILE:.*]] = {{.*}}c"BraceInitEnd.cpp\00"
+// CHECK-AGG-BRACE-DAG: @[[FUNC:.*]] = {{.*}}c"test_agg_init\00"
+//
+// CHECK-AGG-BRACE: define void @test_agg_init()
+// CHECK-AGG-BRACE: %[[I2:.*]] = getelementptr inbounds %struct.TestInitAgg, %struct.TestInitAgg* %local_brace_init, i32 0, i32 1
+// CHECK-AGG-BRACE-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %[[I2]],
+// CHECK-AGG-BRACE-SAME: i32 5700, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
+#line 5600 "BraceInitStart.cpp"
+ TestInitAgg local_brace_init{
+#line 5700 "BraceInitEnd.cpp"
+ };
+
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-AGG-EQUAL
+//
+// CHECK-AGG-EQUAL-DAG: @[[FILE:.*]] = {{.*}}c"EqualInitEnd.cpp\00"
+// CHECK-AGG-EQUAL-DAG: @[[FUNC:.*]] = {{.*}}c"test_agg_init\00"
+//
+// CHECK-AGG-EQUAL: define void @test_agg_init()
+// CHECK-AGG-EQUAL: %[[I2:.*]] = getelementptr inbounds %struct.TestInitAgg, %struct.TestInitAgg* %local_equal_init, i32 0, i32 1
+// CHECK-AGG-EQUAL-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %[[I2]],
+// CHECK-AGG-EQUAL-SAME: i32 5900, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
+#line 5800 "EqualInitStart.cpp"
+ TestInitAgg local_equal_init =
+ {
+#line 5900 "EqualInitEnd.cpp"
+ };
+
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-AGG-LIST
+//
+// CHECK-AGG-LIST-DAG: @[[FILE_DEFAULT:.*]] = {{.*}}c"InitListEnd.cpp\00"
+// CHECK-AGG-LIST-DAG: @[[FILE_ELEM:.*]] = {{.*}}c"ListElem.cpp\00"
+// CHECK-AGG-LIST-DAG: @[[FUNC:.*]] = {{.*}}c"test_agg_init\00"
+//
+// CHECK-AGG-LIST: define void @test_agg_init()
+//
+// CHECK-AGG-LIST: %[[I1:.*]] = getelementptr inbounds %struct.TestInitAgg, %struct.TestInitAgg* %local_list_init, i32 0, i32 0
+// CHECK-AGG-LIST-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %[[I1]],
+// CHECK-AGG-LIST-SAME: i32 6100, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE_ELEM]], {{[^@]*}}@[[FUNC]]
+//
+// CHECK-AGG-LIST: %[[I2:.*]] = getelementptr inbounds %struct.TestInitAgg, %struct.TestInitAgg* %local_list_init, i32 0, i32 1
+// CHECK-AGG-LIST-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %[[I2]],
+// CHECK-AGG-LIST-SAME: i32 6200, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE_DEFAULT]], {{[^@]*}}@[[FUNC]]
+#line 6000 "InitListStart.cpp"
+ TestInitAgg local_list_init =
+ {
+#line 6100 "ListElem.cpp"
+ {SL::current()}
+#line 6200 "InitListEnd.cpp"
+ };
+}
+
+#line 7000 "TestTemplate.cpp"
+template <class Tp, int>
+struct TestTemplate {
+ Tp info = Tp::current();
+ Tp arg_info;
+#line 7100 "TestTemplateCtor.cpp"
+ constexpr TestTemplate(Tp arg_info = Tp::current()) : arg_info(arg_info) {}
+};
+
+#line 7200 "test_template.cpp"
+template <class T, int V>
+void test_template() {
+
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-TEMPL -DINT_ID=0
+// RUN: FileCheck --input-file %t.ll %s --check-prefix=CHECK-TEMPL -DINT_ID=1
+//
+// CHECK-TEMPL-DAG: @[[FILE:.*]] = {{.*}}c"local_templ.cpp\00"
+// CHECK-TEMPL-DAG: @[[FUNC:.*]] = {{.*}}c"test_template\00"
+//
+// CHECK-TEMPL: define weak_odr void @_Z13test_templateI15source_locationLi[[INT_ID]]EEvv()
+// CHECK-TEMPL-NEXT: entry:
+// CHECK-TEMPL-NOT: ret
+//
+// CHECK-TEMPL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret %[[TMP:[^,]*]],
+// CHECK-TEMPL-SAME: i32 7300, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
+#line 7300 "local_templ.cpp"
+ TestTemplate<T, V> local_templ;
+}
+#line 7400 "EndTestTemplate.cpp"
+template void test_template<SL, 0>();
+template void test_template<SL, 1>();
Added: cfe/trunk/test/CodeGenCXX/builtin_FUNCTION.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/builtin_FUNCTION.cpp?rev=360937&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/builtin_FUNCTION.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/builtin_FUNCTION.cpp Thu May 16 14:04:15 2019
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -std=c++2a -fblocks %s -triple %itanium_abi_triple -emit-llvm -o %t.ll
+// RUN: FileCheck --input-file %t.ll %s
+
+namespace test_func {
+
+constexpr const char *test_default_arg(const char *f = __builtin_FUNCTION()) {
+ return f;
+}
+// CHECK: @[[EMPTY_STR:.+]] = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+
+// CHECK: @_ZN9test_func6globalE = global i8* getelementptr inbounds ([1 x i8], [1 x i8]* @[[EMPTY_STR]], i32 0, i32 0), align 8
+const char *global = test_default_arg();
+
+// CHECK: @_ZN9test_func10global_twoE = global i8* getelementptr inbounds ([1 x i8], [1 x i8]* @[[EMPTY_STR]], i32 0, i32 0), align 8
+const char *global_two = __builtin_FUNCTION();
+
+const char * const global_three = test_default_arg();
+
+// CHECK: @[[STR_ONE:.+]] = private unnamed_addr constant [14 x i8] c"test_func_one\00", align 1
+// CHECK: @[[STR_TWO:.+]] = private unnamed_addr constant [14 x i8] c"test_func_two\00", align 1
+// CHECK: @[[STR_THREE:.+]] = private unnamed_addr constant [20 x i8] c"do_default_arg_test\00", align 1
+
+// CHECK: define i8* @_ZN9test_func13test_func_oneEv()
+// CHECK: ret i8* getelementptr inbounds ([14 x i8], [14 x i8]* @[[STR_ONE]], i32 0, i32 0)
+const char *test_func_one() {
+ return __builtin_FUNCTION();
+}
+
+// CHECK: define i8* @_ZN9test_func13test_func_twoEv()
+// CHECK: ret i8* getelementptr inbounds ([14 x i8], [14 x i8]* @[[STR_TWO]], i32 0, i32 0)
+const char *test_func_two() {
+ return __builtin_FUNCTION();
+}
+
+// CHECK: define void @_ZN9test_func19do_default_arg_testEv()
+// CHECK: %call = call i8* @_ZN9test_func16test_default_argEPKc(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @[[STR_THREE]], i32 0, i32 0))
+void do_default_arg_test() {
+ test_default_arg();
+}
+
+} // namespace test_func
Added: cfe/trunk/test/CodeGenCXX/builtin_LINE.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/builtin_LINE.cpp?rev=360937&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/builtin_LINE.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/builtin_LINE.cpp Thu May 16 14:04:15 2019
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 -std=c++1z -fblocks %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
+
+extern "C" int sink;
+extern "C" const volatile void* volatile ptr_sink = nullptr;
+
+struct Tag1 {};
+struct Tag2 {};
+struct Tag3 {};
+struct Tag4 {};
+
+constexpr int get_line_constexpr(int l = __builtin_LINE()) {
+ return l;
+}
+
+int get_line_nonconstexpr(int l = __builtin_LINE()) {
+ return l;
+}
+
+
+int get_line(int l = __builtin_LINE()) {
+ return l;
+}
+
+int get_line2(int l = get_line()) { return l; }
+
+
+// CHECK: @global_one = global i32 [[@LINE+1]], align 4
+int global_one = __builtin_LINE();
+// CHECK-NEXT: @global_two = global i32 [[@LINE+1]], align 4
+int global_two = get_line_constexpr();
+// CHECK: @_ZL12global_three = internal constant i32 [[@LINE+1]], align 4
+const int global_three(get_line_constexpr());
+
+// CHECK-LABEL: define internal void @__cxx_global_var_init
+// CHECK: %call = call i32 @_Z21get_line_nonconstexpri(i32 [[@LINE+2]])
+// CHECK-NEXT: store i32 %call, i32* @global_four, align 4
+int global_four = get_line_nonconstexpr();
+
+struct InClassInit {
+ int Init = __builtin_LINE();
+ int Init2 = get_line2();
+ InClassInit();
+ constexpr InClassInit(Tag1, int l = __builtin_LINE()) : Init(l), Init2(l) {}
+ constexpr InClassInit(Tag2) : Init(__builtin_LINE()), Init2(__builtin_LINE()) {}
+ InClassInit(Tag3, int l = __builtin_LINE());
+ InClassInit(Tag4, int l = get_line2());
+
+ static void test_class();
+};
+// CHECK-LABEL: define void @_ZN11InClassInit10test_classEv()
+void InClassInit::test_class() {
+ // CHECK: call void @_ZN11InClassInitC1Ev(%struct.InClassInit* %test_one)
+ InClassInit test_one;
+ // CHECK-NEXT: call void @_ZN11InClassInitC1E4Tag1i(%struct.InClassInit* %test_two, i32 [[@LINE+1]])
+ InClassInit test_two{Tag1{}};
+ // CHECK-NEXT: call void @_ZN11InClassInitC1E4Tag2(%struct.InClassInit* %test_three)
+ InClassInit test_three{Tag2{}};
+ // CHECK-NEXT: call void @_ZN11InClassInitC1E4Tag3i(%struct.InClassInit* %test_four, i32 [[@LINE+1]])
+ InClassInit test_four(Tag3{});
+ // CHECK-NEXT: %[[CALL:.+]] = call i32 @_Z8get_linei(i32 [[@LINE+3]])
+ // CHECK-NEXT: %[[CALL2:.+]] = call i32 @_Z9get_line2i(i32 %[[CALL]])
+ // CHECK-NEXT: call void @_ZN11InClassInitC1E4Tag4i(%struct.InClassInit* %test_five, i32 %[[CALL2]])
+ InClassInit test_five(Tag4{});
+
+}
+// CHECK-LABEL: define void @_ZN11InClassInitC2Ev
+// CHECK: store i32 [[@LINE+4]], i32* %Init, align 4
+// CHECK: %call = call i32 @_Z8get_linei(i32 [[@LINE+3]])
+// CHECK-NEXT: %call2 = call i32 @_Z9get_line2i(i32 %call)
+// CHECK-NEXT: store i32 %call2, i32* %Init2, align 4
+InClassInit::InClassInit() = default;
+
+InClassInit::InClassInit(Tag3, int l) : Init(l) {}
+
+// CHECK-LABEL: define void @_ZN11InClassInitC2E4Tag4i(%struct.InClassInit* %this, i32 %arg)
+// CHECK: %[[TEMP:.+]] = load i32, i32* %arg.addr, align 4
+// CHECK-NEXT: store i32 %[[TEMP]], i32* %Init, align 4
+// CHECK: %[[CALL:.+]] = call i32 @_Z8get_linei(i32 [[@LINE+3]])
+// CHECK-NEXT: %[[CALL2:.+]] = call i32 @_Z9get_line2i(i32 %[[CALL]])
+// CHECK-NEXT: store i32 %[[CALL2]], i32* %Init2, align 4
+InClassInit::InClassInit(Tag4, int arg) : Init(arg) {}
+
+// CHECK-LABEL: define void @_Z13get_line_testv()
+void get_line_test() {
+ // CHECK: %[[CALL:.+]] = call i32 @_Z8get_linei(i32 [[@LINE+2]])
+ // CHECK-NEXT: store i32 %[[CALL]], i32* @sink, align 4
+ sink = get_line();
+ // CHECK-NEXT: store i32 [[@LINE+1]], i32* @sink, align 4
+ sink = __builtin_LINE();
+ ptr_sink = &global_three;
+}
+
+void foo() {
+ const int N[] = {__builtin_LINE(), get_line_constexpr()};
+}
Modified: cfe/trunk/test/CodeGenCXX/debug-info-line.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-line.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/debug-info-line.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/debug-info-line.cpp Thu May 16 14:04:15 2019
@@ -293,6 +293,13 @@ void f24() {
f24_a();
}
+// CHECK-LABEL: define
+void f25_a(int x = __builtin_LINE()) {}
+void f25() {
+ // CHECK: call void @_Z5f25_ai(i32 2700)
+#line 2700
+ f25_a();
+}
// CHECK: [[DBG_F1]] = !DILocation(line: 100,
// CHECK: [[DBG_FOO_VALUE]] = !DILocation(line: 200,
// CHECK: [[DBG_FOO_REF]] = !DILocation(line: 202,
Added: cfe/trunk/test/Parser/builtin_source_location.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/builtin_source_location.c?rev=360937&view=auto
==============================================================================
--- cfe/trunk/test/Parser/builtin_source_location.c (added)
+++ cfe/trunk/test/Parser/builtin_source_location.c Thu May 16 14:04:15 2019
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int main() {
+ int line = __builtin_LINE();
+ __builtin_LINE(42); // expected-error {{expected ')'}}
+ __builtin_LINE(double); // expected-error {{expected ')'}}
+
+ int column = __builtin_COLUMN();
+ __builtin_COLUMN(42); // expected-error {{expected ')'}}
+ __builtin_COLUMN(double); // expected-error {{expected ')'}}
+
+ const char *func = __builtin_FUNCTION();
+ __builtin_FUNCTION(42); // expected-error {{expected ')'}}
+ __builtin_FUNCTION(double); // expected-error {{expected ')'}}
+
+ const char *file = __builtin_FILE();
+ __builtin_FILE(42); // expected-error {{expected ')'}}
+ __builtin_FILE(double); // expected-error {{expected ')'}}
+}
Added: cfe/trunk/test/Sema/source_location.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/source_location.c?rev=360937&view=auto
==============================================================================
--- cfe/trunk/test/Sema/source_location.c (added)
+++ cfe/trunk/test/Sema/source_location.c Thu May 16 14:04:15 2019
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c90 -fconst-strings -DCONST_STRINGS -verify %s
+// RUN: %clang_cc1 -std=c90 -verify %s
+
+// expected-no-diagnostics
+
+#define IsEqual(L, R) (__builtin_strcmp(L, R) == 0)
+
+const char *const FILE = __builtin_FILE();
+const char *const FUNC = __builtin_FUNCTION();
+const unsigned LINE = __builtin_LINE();
+const unsigned COL = __builtin_COLUMN();
+
+#ifndef CONST_STRINGS
+char *const NCFILE = __builtin_FILE();
+char *const NCFUNC = __builtin_FUNCTION();
+#endif
+
+#ifdef CONST_STRINGS
+_Static_assert(IsEqual(__builtin_FILE(), __FILE__), "");
+_Static_assert(__builtin_LINE() == __LINE__, "");
+_Static_assert(IsEqual("", __builtin_FUNCTION()), "");
+
+#line 42 "my_file.c"
+_Static_assert(__builtin_LINE() == 42, "");
+_Static_assert(IsEqual(__builtin_FILE(), "my_file.c"), "");
+
+_Static_assert(__builtin_COLUMN() == __builtin_strlen("_Static_assert(_"), "");
+
+void foo() {
+ _Static_assert(IsEqual(__builtin_FUNCTION(), "foo"), "");
+}
+#endif // CONST_STRINGS
Added: cfe/trunk/test/SemaCXX/Inputs/source-location-file.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/Inputs/source-location-file.h?rev=360937&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/Inputs/source-location-file.h (added)
+++ cfe/trunk/test/SemaCXX/Inputs/source-location-file.h Thu May 16 14:04:15 2019
@@ -0,0 +1,44 @@
+
+// NOTE: source_location.cpp must include this file after defining
+// std::source_location.
+namespace source_location_file {
+
+constexpr const char *FILE = __FILE__;
+
+constexpr SL global_info = SL::current();
+
+constexpr SL test_function(SL v = SL::current()) {
+ return v;
+}
+
+constexpr SL test_function_indirect() {
+ return test_function();
+}
+
+template <class T, class U = SL>
+constexpr U test_function_template(T, U u = U::current()) {
+ return u;
+}
+
+template <class T, class U = SL>
+constexpr U test_function_template_indirect(T t) {
+ return test_function_template(t);
+}
+
+struct TestClass {
+ SL info = SL::current();
+ SL ctor_info;
+ TestClass() = default;
+ constexpr TestClass(int, SL cinfo = SL::current()) : ctor_info(cinfo) {}
+ template <class T, class U = SL>
+ constexpr TestClass(int, T, U u = U::current()) : ctor_info(u) {}
+};
+
+template <class T = SL>
+struct AggrClass {
+ int x;
+ T info;
+ T init_info = T::current();
+};
+
+} // namespace source_location_file
Added: cfe/trunk/test/SemaCXX/source_location.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/source_location.cpp?rev=360937&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/source_location.cpp (added)
+++ cfe/trunk/test/SemaCXX/source_location.cpp Thu May 16 14:04:15 2019
@@ -0,0 +1,590 @@
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -verify %s
+// expected-no-diagnostics
+
+#define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42)
+#define CURRENT_FROM_MACRO() SL::current()
+#define FORWARD(...) __VA_ARGS__
+
+template <unsigned>
+struct Printer;
+
+namespace std {
+namespace experimental {
+struct source_location {
+private:
+ unsigned int __m_line = 0;
+ unsigned int __m_col = 0;
+ const char *__m_file = nullptr;
+ const char *__m_func = nullptr;
+public:
+ static constexpr source_location current(
+ const char *__file = __builtin_FILE(),
+ const char *__func = __builtin_FUNCTION(),
+ unsigned int __line = __builtin_LINE(),
+ unsigned int __col = __builtin_COLUMN()) noexcept {
+ source_location __loc;
+ __loc.__m_line = __line;
+ __loc.__m_col = __col;
+ __loc.__m_file = __file;
+ __loc.__m_func = __func;
+ return __loc;
+ }
+ constexpr source_location() = default;
+ constexpr source_location(source_location const &) = default;
+ constexpr unsigned int line() const noexcept { return __m_line; }
+ constexpr unsigned int column() const noexcept { return __m_col; }
+ constexpr const char *file() const noexcept { return __m_file; }
+ constexpr const char *function() const noexcept { return __m_func; }
+};
+} // namespace experimental
+} // namespace std
+
+using SL = std::experimental::source_location;
+
+#include "Inputs/source-location-file.h"
+namespace SLF = source_location_file;
+
+constexpr bool is_equal(const char *LHS, const char *RHS) {
+ while (*LHS != 0 && *RHS != 0) {
+ if (*LHS != *RHS)
+ return false;
+ ++LHS;
+ ++RHS;
+ }
+ return *LHS == 0 && *RHS == 0;
+}
+
+template <class T>
+constexpr T identity(T t) {
+ return t;
+}
+
+template <class T, class U>
+struct Pair {
+ T first;
+ U second;
+};
+
+template <class T, class U>
+constexpr bool is_same = false;
+template <class T>
+constexpr bool is_same<T, T> = true;
+
+// test types
+static_assert(is_same<decltype(__builtin_LINE()), unsigned>);
+static_assert(is_same<decltype(__builtin_COLUMN()), unsigned>);
+static_assert(is_same<decltype(__builtin_FILE()), const char *>);
+static_assert(is_same<decltype(__builtin_FUNCTION()), const char *>);
+
+// test noexcept
+static_assert(noexcept(__builtin_LINE()));
+static_assert(noexcept(__builtin_COLUMN()));
+static_assert(noexcept(__builtin_FILE()));
+static_assert(noexcept(__builtin_FUNCTION()));
+
+//===----------------------------------------------------------------------===//
+// __builtin_LINE()
+//===----------------------------------------------------------------------===//
+
+namespace test_line {
+static_assert(SL::current().line() == __LINE__);
+static_assert(SL::current().line() == CURRENT_FROM_MACRO().line());
+
+static constexpr SL GlobalS = SL::current();
+
+static_assert(GlobalS.line() == __LINE__ - 2);
+
+// clang-format off
+constexpr bool test_line_fn() {
+ constexpr SL S = SL::current();
+ static_assert(S.line() == (__LINE__ - 1), "");
+ // The start of the call expression to `current()` begins at the token `SL`
+ constexpr int ExpectLine = __LINE__ + 3;
+ constexpr SL S2
+ =
+ SL // Call expression starts here
+ ::
+ current
+ (
+
+ )
+ ;
+ static_assert(S2.line() == ExpectLine, "");
+
+ static_assert(
+ FORWARD(
+ __builtin_LINE
+ (
+ )
+ )
+ == __LINE__ - 1, "");
+ static_assert(\
+\
+ __builtin_LINE()\
+\
+ == __LINE__ - 2, "");
+ static_assert(\
+ _\
+_builtin_LINE()
+ == __LINE__ - 2, "");
+
+ return true;
+}
+// clang-format on
+static_assert(test_line_fn());
+
+static_assert(__builtin_LINE() == __LINE__, "");
+
+constexpr int baz() { return 101; }
+
+constexpr int test_line_fn_simple(int z = baz(), int x = __builtin_LINE()) {
+ return x;
+}
+void bar() {
+ static_assert(test_line_fn_simple() == __LINE__, "");
+ static_assert(test_line_fn_simple() == __LINE__, "");
+}
+
+struct CallExpr {
+ constexpr int operator()(int x = __builtin_LINE()) const { return x; }
+};
+constexpr CallExpr get_call() { return CallExpr{}; }
+static_assert(get_call()() == __LINE__, "");
+
+template <class T>
+constexpr bool test_line_fn_template(T Expect, int L = __builtin_LINE()) {
+ return Expect == L;
+}
+static_assert(test_line_fn_template(__LINE__));
+
+struct InMemInit {
+ constexpr bool check(int expect) const {
+ return info.line() == expect;
+ }
+ SL info = SL::current();
+ InMemInit() = default;
+ constexpr InMemInit(int) {}
+};
+static_assert(InMemInit{}.check(__LINE__ - 3), "");
+static_assert(InMemInit{42}.check(__LINE__ - 3), "");
+
+template <class T, class U = SL>
+struct InMemInitTemplate {
+ constexpr bool check(int expect) const {
+ return info.line() == expect;
+ }
+ U info = U::current();
+ InMemInitTemplate() = default;
+ constexpr InMemInitTemplate(T) {}
+ constexpr InMemInitTemplate(T, T) : info(U::current()) {}
+ template <class V = U> constexpr InMemInitTemplate(T, T, T, V info = U::current())
+ : info(info) {}
+};
+void test_mem_init_template() {
+ constexpr int line_offset = 8;
+ static_assert(InMemInitTemplate<int>{}.check(__LINE__ - line_offset), "");
+ static_assert(InMemInitTemplate<unsigned>{42}.check(__LINE__ - line_offset), "");
+ static_assert(InMemInitTemplate<unsigned>{42, 42}.check(__LINE__ - line_offset), "");
+ static_assert(InMemInitTemplate<unsigned>{42, 42, 42}.check(__LINE__), "");
+}
+
+struct AggInit {
+ int x;
+ int y = __builtin_LINE();
+ constexpr bool check(int expect) const {
+ return y == expect;
+ }
+};
+constexpr AggInit AI{42};
+static_assert(AI.check(__LINE__ - 1), "");
+
+template <class T, class U = SL>
+struct AggInitTemplate {
+ constexpr bool check(int expect) const {
+ return expect == info.line();
+ }
+ T x;
+ U info = U::current();
+};
+
+template <class T, class U = SL>
+constexpr U test_fn_template(T, U u = U::current()) {
+ return u;
+}
+void fn_template_tests() {
+ static_assert(test_fn_template(42).line() == __LINE__, "");
+}
+
+struct TestMethodTemplate {
+ template <class T, class U = SL, class U2 = SL>
+ constexpr U get(T, U u = U::current(), U2 u2 = identity(U2::current())) const {
+ assert(u.line() == u2.line());
+ return u;
+ }
+};
+void method_template_tests() {
+ static_assert(TestMethodTemplate{}.get(42).line() == __LINE__, "");
+}
+
+struct InStaticInit {
+ static constexpr int LINE = __LINE__;
+ static constexpr const int x1 = __builtin_LINE();
+ static constexpr const int x2 = identity(__builtin_LINE());
+ static const int x3;
+ const int x4 = __builtin_LINE();
+ int x5 = __builtin_LINE();
+};
+const int InStaticInit::x3 = __builtin_LINE();
+static_assert(InStaticInit::x1 == InStaticInit::LINE + 1, "");
+static_assert(InStaticInit::x2 == InStaticInit::LINE + 2, "");
+
+template <class T, int N = __builtin_LINE(), int Expect = -1>
+constexpr void check_fn_template_param(T) {
+ constexpr int RealExpect = Expect == -1 ? __LINE__ - 2 : Expect;
+ static_assert(N == RealExpect);
+}
+template void check_fn_template_param(int);
+template void check_fn_template_param<long, 42, 42>(long);
+
+#line 100
+struct AggBase {
+#line 200
+ int x = __builtin_LINE();
+ int y = __builtin_LINE();
+ int z = __builtin_LINE();
+};
+#line 300
+struct AggDer : AggBase {
+};
+#line 400
+static_assert(AggDer{}.x == 400, "");
+
+struct ClassBase {
+#line 400
+ int x = __builtin_LINE();
+ int y = 0;
+ int z = 0;
+#line 500
+ ClassBase() = default;
+ constexpr ClassBase(int yy, int zz = __builtin_LINE())
+ : y(yy), z(zz) {}
+};
+struct ClassDer : ClassBase {
+#line 600
+ ClassDer() = default;
+ constexpr ClassDer(int yy) : ClassBase(yy) {}
+ constexpr ClassDer(int yy, int zz) : ClassBase(yy, zz) {}
+};
+#line 700
+static_assert(ClassDer{}.x == 500, "");
+static_assert(ClassDer{42}.x == 501, "");
+static_assert(ClassDer{42}.z == 601, "");
+static_assert(ClassDer{42, 42}.x == 501, "");
+
+struct ClassAggDer : AggBase {
+#line 800
+ ClassAggDer() = default;
+ constexpr ClassAggDer(int, int x = __builtin_LINE()) : AggBase{x} {}
+};
+static_assert(ClassAggDer{}.x == 100, "");
+
+} // namespace test_line
+
+//===----------------------------------------------------------------------===//
+// __builtin_FILE()
+//===----------------------------------------------------------------------===//
+
+namespace test_file {
+constexpr const char *test_file_simple(const char *__f = __builtin_FILE()) {
+ return __f;
+}
+void test_function() {
+#line 900
+ static_assert(is_equal(test_file_simple(), __FILE__));
+ static_assert(is_equal(SLF::test_function().file(), __FILE__), "");
+ static_assert(is_equal(SLF::test_function_template(42).file(), __FILE__), "");
+
+ static_assert(is_equal(SLF::test_function_indirect().file(), SLF::global_info.file()), "");
+ static_assert(is_equal(SLF::test_function_template_indirect(42).file(), SLF::global_info.file()), "");
+
+ static_assert(test_file_simple() != nullptr);
+ static_assert(!is_equal(test_file_simple(), "source_location.cpp"));
+}
+
+void test_class() {
+#line 315
+ using SLF::TestClass;
+ constexpr TestClass Default;
+ constexpr TestClass InParam{42};
+ constexpr TestClass Template{42, 42};
+ constexpr auto *F = Default.info.file();
+ constexpr auto Char = F[0];
+ static_assert(is_equal(Default.info.file(), SLF::FILE), "");
+ static_assert(is_equal(InParam.info.file(), SLF::FILE), "");
+ static_assert(is_equal(InParam.ctor_info.file(), __FILE__), "");
+}
+
+void test_aggr_class() {
+ using Agg = SLF::AggrClass<>;
+ constexpr Agg Default{};
+ constexpr Agg InitOne{42};
+ static_assert(is_equal(Default.init_info.file(), __FILE__), "");
+ static_assert(is_equal(InitOne.init_info.file(), __FILE__), "");
+}
+
+} // namespace test_file
+
+//===----------------------------------------------------------------------===//
+// __builtin_FUNCTION()
+//===----------------------------------------------------------------------===//
+
+namespace test_func {
+
+constexpr const char *test_func_simple(const char *__f = __builtin_FUNCTION()) {
+ return __f;
+}
+constexpr const char *get_function() {
+ return __func__;
+}
+constexpr bool test_function() {
+ return is_equal(__func__, test_func_simple()) &&
+ !is_equal(get_function(), test_func_simple());
+}
+static_assert(test_function());
+
+template <class T, class U = SL>
+constexpr Pair<U, U> test_func_template(T, U u = U::current()) {
+ static_assert(is_equal(__func__, U::current().function()));
+ return {u, U::current()};
+}
+template <class T>
+void func_template_tests() {
+ constexpr auto P = test_func_template(42);
+ //static_assert(is_equal(P.first.function(), __func__), "");
+ //static_assert(!is_equal(P.second.function(), __func__), "");
+}
+template void func_template_tests<int>();
+
+template <class = int, class T = SL>
+struct TestCtor {
+ T info = T::current();
+ T ctor_info;
+ TestCtor() = default;
+ template <class U = SL>
+ constexpr TestCtor(int, U u = U::current()) : ctor_info(u) {}
+};
+void ctor_tests() {
+ constexpr TestCtor<> Default;
+ constexpr TestCtor<> Template{42};
+ static_assert(!is_equal(Default.info.function(), __func__));
+ static_assert(is_equal(Default.info.function(), "TestCtor"));
+ static_assert(is_equal(Template.info.function(), "TestCtor"));
+ static_assert(is_equal(Template.ctor_info.function(), __func__));
+}
+
+constexpr SL global_sl = SL::current();
+static_assert(is_equal(global_sl.function(), ""));
+
+} // namespace test_func
+
+//===----------------------------------------------------------------------===//
+// __builtin_COLUMN()
+//===----------------------------------------------------------------------===//
+
+namespace test_column {
+
+// clang-format off
+constexpr bool test_column_fn() {
+ constexpr SL S = SL::current();
+ static_assert(S.line() == (__LINE__ - 1), "");
+ constexpr int Indent = 4;
+ {
+ // The start of the call expression to `current()` begins at the token `SL`
+ constexpr int ExpectCol = Indent + 3;
+ constexpr SL S2
+ =
+ SL // Call expression starts here
+ ::
+ current
+ (
+
+ )
+ ;
+ static_assert(S2.column() == ExpectCol, "");
+ }
+ {
+ constexpr int ExpectCol = 2;
+ constexpr int C =
+ __builtin_COLUMN // Expect call expression to start here
+ ();
+ static_assert(C == ExpectCol);
+ }
+ return true;
+}
+#line 420
+static_assert(test_column_fn());
+
+// Test that the column matches the start of the call expression 'SL::current()'
+static_assert(SL::current().column() == __builtin_strlen("static_assert(S"));
+struct TestClass {
+ int x = __builtin_COLUMN();
+ TestClass() = default; /* indented to 3 spaces for testing */
+ constexpr TestClass(int, int o = __builtin_COLUMN()) : x(o) {}
+};
+struct TestAggClass {
+ int x = __builtin_COLUMN();
+};
+constexpr bool test_class() {
+
+ auto check = [](int V, const char* S, int indent = 4) {
+ assert(V == (__builtin_strlen(S) + indent));
+ };
+ {
+ TestClass t{};
+ check(t.x, " T", 0); // Start of default constructor decl.
+ }
+ {
+ TestClass t1
+ {42};
+ check(t1.x, "TestClass t"); // Start of variable being constructed.
+ }
+ {
+ TestAggClass t { };
+ check(t.x, "TestAggClass t { }");
+ }
+ {
+ TestAggClass t = { };
+ check(t.x, "TestAggClass t = { }");
+ }
+ return true;
+}
+static_assert(test_class());
+// clang-format on
+} // namespace test_column
+
+// Test [reflection.src_loc.creation]p2
+// > The value should be affected by #line (C++14 16.4) in the same manner as
+// > for __LINE__ and __FILE__.
+namespace test_pragma_line {
+constexpr int StartLine = 42;
+#line 42
+static_assert(__builtin_LINE() == StartLine);
+static_assert(__builtin_LINE() == StartLine + 1);
+static_assert(SL::current().line() == StartLine + 2);
+#line 44 "test_file.c"
+static_assert(is_equal("test_file.c", __FILE__));
+static_assert(is_equal("test_file.c", __builtin_FILE()));
+static_assert(is_equal("test_file.c", SL::current().file()));
+static_assert(is_equal("test_file.c", SLF::test_function().file()));
+static_assert(is_equal(SLF::FILE, SLF::test_function_indirect().file()));
+} // end namespace test_pragma_line
+
+namespace test_out_of_line_init {
+#line 4000 "test_out_of_line_init.cpp"
+constexpr unsigned get_line(unsigned n = __builtin_LINE()) { return n; }
+constexpr const char *get_file(const char *f = __builtin_FILE()) { return f; }
+constexpr const char *get_func(const char *f = __builtin_FUNCTION()) { return f; }
+#line 4100 "A.cpp"
+struct A {
+ int n = __builtin_LINE();
+ int n2 = get_line();
+ const char *f = __builtin_FILE();
+ const char *f2 = get_file();
+ const char *func = __builtin_FUNCTION();
+ const char *func2 = get_func();
+ SL info = SL::current();
+};
+#line 4200 "B.cpp"
+struct B {
+ A a = {};
+};
+#line 4300 "test_passed.cpp"
+constexpr B b = {};
+static_assert(b.a.n == 4300, "");
+static_assert(b.a.n2 == 4300, "");
+static_assert(b.a.info.line() == 4300, "");
+static_assert(is_equal(b.a.f, "test_passed.cpp"));
+static_assert(is_equal(b.a.f2, "test_passed.cpp"));
+static_assert(is_equal(b.a.info.file(), "test_passed.cpp"));
+static_assert(is_equal(b.a.func, ""));
+static_assert(is_equal(b.a.func2, ""));
+static_assert(is_equal(b.a.info.function(), ""));
+
+constexpr bool test_in_func() {
+#line 4400 "test_func_passed.cpp"
+ constexpr B b = {};
+ static_assert(b.a.n == 4400, "");
+ static_assert(b.a.n2 == 4400, "");
+ static_assert(b.a.info.line() == 4400, "");
+ static_assert(is_equal(b.a.f, "test_func_passed.cpp"));
+ static_assert(is_equal(b.a.f2, "test_func_passed.cpp"));
+ static_assert(is_equal(b.a.info.file(), "test_func_passed.cpp"));
+ static_assert(is_equal(b.a.func, "test_in_func"));
+ static_assert(is_equal(b.a.func2, "test_in_func"));
+ static_assert(is_equal(b.a.info.function(), "test_in_func"));
+ return true;
+}
+static_assert(test_in_func());
+
+} // end namespace test_out_of_line_init
+
+namespace test_global_scope {
+#line 5000 "test_global_scope.cpp"
+constexpr unsigned get_line(unsigned n = __builtin_LINE()) { return n; }
+constexpr const char *get_file(const char *f = __builtin_FILE()) { return f; }
+constexpr const char *get_func(const char *f = __builtin_FUNCTION()) { return f; }
+#line 5100
+struct InInit {
+ unsigned l = get_line();
+ const char *f = get_file();
+ const char *func = get_func();
+
+#line 5200 "in_init.cpp"
+ constexpr InInit() {}
+};
+#line 5300
+constexpr InInit II;
+
+static_assert(II.l == 5200, "");
+static_assert(is_equal(II.f, "in_init.cpp"));
+static_assert(is_equal(II.func, "InInit"));
+
+#line 5400
+struct AggInit {
+ unsigned l = get_line();
+ const char *f = get_file();
+ const char *func = get_func();
+};
+#line 5500 "brace_init.cpp"
+constexpr AggInit AI = {};
+static_assert(AI.l == 5500);
+static_assert(is_equal(AI.f, "brace_init.cpp"));
+static_assert(is_equal(AI.func, ""));
+
+} // namespace test_global_scope
+
+namespace TestFuncInInit {
+#line 6000 "InitClass.cpp"
+struct Init {
+ SL info;
+#line 6100 "InitCtor.cpp"
+ constexpr Init(SL info = SL::current()) : info(info) {}
+};
+#line 6200 "InitGlobal.cpp"
+constexpr Init I;
+static_assert(I.info.line() == 6200);
+static_assert(is_equal(I.info.file(), "InitGlobal.cpp"));
+
+} // namespace TestFuncInInit
+
+namespace TestConstexprContext {
+#line 7000 "TestConstexprContext.cpp"
+ constexpr const char* foo() { return __builtin_FILE(); }
+#line 7100 "Bar.cpp"
+ constexpr const char* bar(const char* x = foo()) { return x; }
+ constexpr bool test() {
+ static_assert(is_equal(bar(), "TestConstexprContext.cpp"));
+ return true;
+ }
+ static_assert(test());
+}
Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=360937&r1=360936&r2=360937&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Thu May 16 14:04:15 2019
@@ -282,6 +282,7 @@ CXCursor cxcursor::MakeCXCursor(const St
case Stmt::ParenListExprClass:
case Stmt::PredefinedExprClass:
case Stmt::ShuffleVectorExprClass:
+ case Stmt::SourceLocExprClass:
case Stmt::ConvertVectorExprClass:
case Stmt::VAArgExprClass:
case Stmt::ObjCArrayLiteralClass:
More information about the cfe-commits
mailing list