summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTDumper.cpp10
-rw-r--r--clang/lib/AST/Expr.cpp53
-rw-r--r--clang/lib/AST/ExprConstant.cpp8
-rw-r--r--clang/lib/AST/StmtPrinter.cpp23
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp91
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp5
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h3
-rw-r--r--clang/lib/Sema/SemaExpr.cpp35
-rw-r--r--clang/lib/Sema/TreeTransform.h15
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp3
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp1
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp2
12 files changed, 122 insertions, 127 deletions
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index d134e646eb9..25ed2cda26a 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -1714,15 +1714,7 @@ void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
VisitExpr(Node);
- switch (Node->getIdentType()) {
- default: llvm_unreachable("unknown case");
- case PredefinedExpr::Func: OS << " __func__"; break;
- case PredefinedExpr::Function: OS << " __FUNCTION__"; break;
- case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break;
- case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break;
- case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
- case PredefinedExpr::FuncSig: OS << " __FUNCSIG__"; break;
- }
+ OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType());
}
void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 0970d59c9c5..8410bad88d9 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -448,6 +448,38 @@ SourceLocation DeclRefExpr::getLocEnd() const {
return getNameInfo().getLocEnd();
}
+PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
+ StringLiteral *SL)
+ : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary,
+ FNTy->isDependentType(), FNTy->isDependentType(),
+ FNTy->isInstantiationDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(L), Type(IT), FnName(SL) {}
+
+StringLiteral *PredefinedExpr::getFunctionName() {
+ return cast<StringLiteral>(FnName);
+}
+
+StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) {
+ switch (IT) {
+ case Func:
+ return "__func__";
+ case Function:
+ return "__FUNCTION__";
+ case FuncDName:
+ return "__FUNCDNAME__";
+ case LFunction:
+ return "L__FUNCTION__";
+ case PrettyFunction:
+ return "__PRETTY_FUNCTION__";
+ case FuncSig:
+ return "__FUNCSIG__";
+ case PrettyFunctionNoVirtual:
+ break;
+ }
+ llvm_unreachable("Unknown ident type for PredefinedExpr");
+}
+
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
// expr" policy instead.
std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
@@ -477,6 +509,22 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
}
return "";
}
+ if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) {
+ std::unique_ptr<MangleContext> MC;
+ MC.reset(Context.createMangleContext());
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ auto DC = CurrentDecl->getDeclContext();
+ if (DC->isFileContext())
+ MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out);
+ else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
+ MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
+ else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
+ MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
+ else
+ MC->mangleBlock(DC, BD, Out);
+ return Out.str();
+ }
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
return FD->getNameAsString();
@@ -600,9 +648,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
// type deduction and lambdas. For trailing return types resolve the
// decltype expression. Otherwise print the real type when this is
// not a constructor or destructor.
- if ((isa<CXXMethodDecl>(FD) &&
- cast<CXXMethodDecl>(FD)->getParent()->isLambda()) ||
- (FT && FT->getReturnType()->getAs<AutoType>()))
+ if (isa<CXXMethodDecl>(FD) &&
+ cast<CXXMethodDecl>(FD)->getParent()->isLambda())
Proto = "auto " + Proto;
else if (FT && FT->getReturnType()->getAs<DecltypeType>())
FT->getReturnType()
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 74bc31db34f..f7eef828063 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2021,7 +2021,9 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived,
/// Extract the value of a character from a string literal.
static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
uint64_t Index) {
- // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
+ // FIXME: Support ObjCEncodeExpr, MakeStringConstant
+ if (auto PE = dyn_cast<PredefinedExpr>(Lit))
+ Lit = PE->getFunctionName();
const StringLiteral *S = cast<StringLiteral>(Lit);
const ConstantArrayType *CAT =
Info.Ctx.getAsConstantArrayType(S->getType());
@@ -2715,10 +2717,10 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
return false;
CompleteObject LitObj(&Lit, Base->getType());
return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal);
- } else if (isa<StringLiteral>(Base)) {
+ } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) {
// We represent a string literal array as an lvalue pointing at the
// corresponding expression, rather than building an array of chars.
- // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
+ // FIXME: Support ObjCEncodeExpr, MakeStringConstant
APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0);
CompleteObject StrObj(&Str, Base->getType());
return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal);
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 301d6a7bb68..c84875c09fb 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1004,28 +1004,7 @@ void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
}
void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
- switch (Node->getIdentType()) {
- default:
- llvm_unreachable("unknown case");
- case PredefinedExpr::Func:
- OS << "__func__";
- break;
- case PredefinedExpr::Function:
- OS << "__FUNCTION__";
- break;
- case PredefinedExpr::FuncDName:
- OS << "__FUNCDNAME__";
- break;
- case PredefinedExpr::FuncSig:
- OS << "__FUNCSIG__";
- break;
- case PredefinedExpr::LFunction:
- OS << "L__FUNCTION__";
- break;
- case PredefinedExpr::PrettyFunction:
- OS << "__PRETTY_FUNCTION__";
- break;
- }
+ OS << PredefinedExpr::getIdentTypeName(Node->getIdentType());
}
void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 518d81bd361..19f6e949990 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/Attr.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
@@ -2069,86 +2070,18 @@ LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
E->getType());
}
-static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
- SmallString<32>& Target) {
- Target.resize(CharByteWidth * (Source.size() + 1));
- char *ResultPtr = &Target[0];
- const UTF8 *ErrorPtr;
- bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
- (void)success;
- assert(success);
- Target.resize(ResultPtr - &Target[0]);
-}
-
LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
- switch (E->getIdentType()) {
- default:
- return EmitUnsupportedLValue(E, "predefined expression");
-
- case PredefinedExpr::Func:
- case PredefinedExpr::Function:
- case PredefinedExpr::LFunction:
- case PredefinedExpr::FuncDName:
- case PredefinedExpr::FuncSig:
- case PredefinedExpr::PrettyFunction: {
- PredefinedExpr::IdentType IdentType = E->getIdentType();
- std::string GVName;
-
- // FIXME: We should use the string literal mangling for the Microsoft C++
- // ABI so that strings get merged.
- switch (IdentType) {
- default: llvm_unreachable("Invalid type");
- case PredefinedExpr::Func: GVName = "__func__."; break;
- case PredefinedExpr::Function: GVName = "__FUNCTION__."; break;
- case PredefinedExpr::FuncDName: GVName = "__FUNCDNAME__."; break;
- case PredefinedExpr::FuncSig: GVName = "__FUNCSIG__."; break;
- case PredefinedExpr::LFunction: GVName = "L__FUNCTION__."; break;
- case PredefinedExpr::PrettyFunction: GVName = "__PRETTY_FUNCTION__."; break;
- }
-
- StringRef FnName = CurFn->getName();
- if (FnName.startswith("\01"))
- FnName = FnName.substr(1);
- GVName += FnName;
-
- // If this is outside of a function use the top level decl.
- const Decl *CurDecl = CurCodeDecl;
- if (!CurDecl || isa<VarDecl>(CurDecl))
- CurDecl = getContext().getTranslationUnitDecl();
-
- const Type *ElemType = E->getType()->getArrayElementTypeNoTypeQual();
- std::string FunctionName;
- if (isa<BlockDecl>(CurDecl)) {
- // Blocks use the mangled function name.
- // FIXME: ComputeName should handle blocks.
- FunctionName = FnName.str();
- } else if (isa<CapturedDecl>(CurDecl)) {
- // For a captured statement, the function name is its enclosing
- // function name not the one compiler generated.
- FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl);
- } else {
- FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl);
- assert(cast<ConstantArrayType>(E->getType())->getSize() - 1 ==
- FunctionName.size() &&
- "Computed __func__ length differs from type!");
- }
-
- llvm::Constant *C;
- if (ElemType->isWideCharType()) {
- SmallString<32> RawChars;
- ConvertUTF8ToWideString(
- getContext().getTypeSizeInChars(ElemType).getQuantity(), FunctionName,
- RawChars);
- StringLiteral *SL = StringLiteral::Create(
- getContext(), RawChars, StringLiteral::Wide,
- /*Pascal = */ false, E->getType(), E->getLocation());
- C = CGM.GetAddrOfConstantStringFromLiteral(SL);
- } else {
- C = CGM.GetAddrOfConstantCString(FunctionName, GVName.c_str(), 1);
- }
- return MakeAddrLValue(C, E->getType());
- }
- }
+ auto SL = E->getFunctionName();
+ assert(SL != nullptr && "No StringLiteral name in PredefinedExpr");
+ StringRef FnName = CurFn->getName();
+ if (FnName.startswith("\01"))
+ FnName = FnName.substr(1);
+ StringRef NameItems[] = {
+ PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName};
+ std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
+
+ auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName);
+ return MakeAddrLValue(C, E->getType());
}
/// Emit a type description suitable for use by a runtime sanitizer library. The
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index a7a65b88c91..5d314f525cd 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2729,7 +2729,8 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
/// GetAddrOfConstantStringFromLiteral - Return a pointer to a
/// constant array for the given string literal.
llvm::GlobalVariable *
-CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
+CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
+ StringRef Name) {
auto Alignment =
getContext().getAlignOfGlobalVarInChars(S->getType()).getQuantity();
@@ -2761,7 +2762,7 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
GlobalVariableName = MangledNameBuffer;
} else {
LT = llvm::GlobalValue::PrivateLinkage;
- GlobalVariableName = ".str";
+ GlobalVariableName = Name;
}
auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment);
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 955f665f86c..665a7a589f8 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -785,7 +785,8 @@ public:
/// Return a pointer to a constant array for the given string literal.
llvm::GlobalVariable *
- GetAddrOfConstantStringFromLiteral(const StringLiteral *S);
+ GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
+ StringRef Name = ".str");
/// Return a pointer to a constant array for the given ObjCEncodeExpr node.
llvm::GlobalVariable *
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0c7cb2e6df1..40909534629 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -42,6 +42,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaFixItUtils.h"
#include "clang/Sema/Template.h"
+#include "llvm/Support/ConvertUTF.h"
using namespace clang;
using namespace sema;
@@ -2905,6 +2906,17 @@ ExprResult Sema::BuildDeclarationNameExpr(
}
}
+static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
+ SmallString<32> &Target) {
+ Target.resize(CharByteWidth * (Source.size() + 1));
+ char *ResultPtr = &Target[0];
+ const UTF8 *ErrorPtr;
+ bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
+ (void)success;
+ assert(success);
+ Target.resize(ResultPtr - &Target[0]);
+}
+
ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
PredefinedExpr::IdentType IT) {
// Pick the current block, lambda, captured statement or function.
@@ -2924,22 +2936,35 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
}
QualType ResTy;
+ StringLiteral *SL = nullptr;
if (cast<DeclContext>(currentDecl)->isDependentContext())
ResTy = Context.DependentTy;
else {
// Pre-defined identifiers are of type char[x], where x is the length of
// the string.
- unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
+ auto Str = PredefinedExpr::ComputeName(IT, currentDecl);
+ unsigned Length = Str.length();
llvm::APInt LengthI(32, Length + 1);
- if (IT == PredefinedExpr::LFunction)
+ if (IT == PredefinedExpr::LFunction) {
ResTy = Context.WideCharTy.withConst();
- else
+ SmallString<32> RawChars;
+ ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
+ Str, RawChars);
+ ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
+ /*IndexTypeQuals*/ 0);
+ SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide,
+ /*Pascal*/ false, ResTy, Loc);
+ } else {
ResTy = Context.CharTy.withConst();
- ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+ ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
+ /*IndexTypeQuals*/ 0);
+ SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
+ /*Pascal*/ false, ResTy, Loc);
+ }
}
- return new (Context) PredefinedExpr(Loc, ResTy, IT);
+ return new (Context) PredefinedExpr(Loc, ResTy, IT, SL);
}
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 08a134a30be..df4ab10e748 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1677,6 +1677,15 @@ public:
return getSema().ActOnSEHFinallyBlock(Loc, Block);
}
+ /// \brief Build a new predefined expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentType IT) {
+ return getSema().BuildPredefinedExpr(Loc, IT);
+ }
+
/// \brief Build a new expression that references a declaration.
///
/// By default, performs semantic analysis to build the new expression.
@@ -7016,7 +7025,11 @@ OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
- return E;
+ if (!E->isTypeDependent())
+ return E;
+
+ return getDerived().RebuildPredefinedExpr(E->getLocation(),
+ E->getIdentType());
}
template<typename Derived>
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 811427e359f..61e509b254f 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -422,7 +422,8 @@ void ASTStmtReader::VisitExpr(Expr *E) {
void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
E->setLocation(ReadSourceLocation(Record, Idx));
- E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
+ E->Type = (PredefinedExpr::IdentType)Record[Idx++];
+ E->FnName = cast<StringLiteral>(Reader.ReadSubExpr());
}
void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index d91e2be361b..ff42c8301d9 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -333,6 +333,7 @@ void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->getIdentType()); // FIXME: stable encoding
+ Writer.AddStmt(E->getFunctionName());
Code = serialization::EXPR_PREDEFINED;
}
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 807d5216e88..c844147e35c 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -868,7 +868,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ObjCProtocolExprClass:
case Stmt::ObjCSelectorExprClass:
case Stmt::ParenListExprClass:
- case Stmt::PredefinedExprClass:
case Stmt::ShuffleVectorExprClass:
case Stmt::ConvertVectorExprClass:
case Stmt::VAArgExprClass:
@@ -880,6 +879,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
// Cases we intentionally don't evaluate, since they don't need
// to be explicitly evaluated.
+ case Stmt::PredefinedExprClass:
case Stmt::AddrLabelExprClass:
case Stmt::AttributedStmtClass:
case Stmt::IntegerLiteralClass:
OpenPOWER on IntegriCloud