aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-05-27 18:47:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-05-27 18:47:56 +0000
commit5e20cdd81c44a443562a09007668ffdf76c455af (patch)
treedbbd4047878da71c1a706e26ce05b4e7791b14cc /lib/AST
parentd5f23b0b7528b5c3caed1ba14f897cc4aaa9e3c3 (diff)
downloadsrc-434ab66796bbe752e77357049917ed2c57e74a5d.tar.gz
src-434ab66796bbe752e77357049917ed2c57e74a5d.zip
Vendor import of clang trunk r238337:vendor/clang/clang-trunk-r238337
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTContext.cpp144
-rw-r--r--lib/AST/ASTDumper.cpp56
-rw-r--r--lib/AST/ASTImporter.cpp753
-rw-r--r--lib/AST/AttrImpl.cpp8
-rw-r--r--lib/AST/CXXABI.h16
-rw-r--r--lib/AST/CXXInheritance.cpp138
-rw-r--r--lib/AST/CommentLexer.cpp6
-rw-r--r--lib/AST/Decl.cpp282
-rw-r--r--lib/AST/DeclBase.cpp210
-rw-r--r--lib/AST/DeclCXX.cpp32
-rw-r--r--lib/AST/DeclGroup.cpp2
-rw-r--r--lib/AST/DeclObjC.cpp31
-rw-r--r--lib/AST/DeclTemplate.cpp86
-rw-r--r--lib/AST/Expr.cpp140
-rw-r--r--lib/AST/ExprCXX.cpp21
-rw-r--r--lib/AST/ExprClassification.cpp12
-rw-r--r--lib/AST/ExprConstant.cpp49
-rw-r--r--lib/AST/ExternalASTSource.cpp5
-rw-r--r--lib/AST/InheritViz.cpp19
-rw-r--r--lib/AST/ItaniumCXXABI.cpp18
-rw-r--r--lib/AST/ItaniumMangle.cpp749
-rw-r--r--lib/AST/MicrosoftCXXABI.cpp55
-rw-r--r--lib/AST/MicrosoftMangle.cpp451
-rw-r--r--lib/AST/NSAPI.cpp102
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp221
-rw-r--r--lib/AST/Stmt.cpp230
-rw-r--r--lib/AST/StmtPrinter.cpp56
-rw-r--r--lib/AST/StmtProfile.cpp52
-rw-r--r--lib/AST/Type.cpp34
-rw-r--r--lib/AST/TypePrinter.cpp24
-rw-r--r--lib/AST/VTableBuilder.cpp223
31 files changed, 3072 insertions, 1153 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index c9fb80ceaae2..4a831d90e645 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -738,9 +738,9 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr),
ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
- FirstLocalImport(), LastLocalImport(),
+ FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
SourceMgr(SM), LangOpts(LOpts),
- SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFile, SM)),
+ SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts),
Idents(idents), Selectors(sels), BuiltinInfo(builtins),
DeclarationNames(*this), ExternalSource(nullptr), Listener(nullptr),
@@ -866,6 +866,38 @@ void ASTContext::PrintStats() const {
BumpAlloc.PrintStats();
}
+void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
+ bool NotifyListeners) {
+ if (NotifyListeners)
+ if (auto *Listener = getASTMutationListener())
+ Listener->RedefinedHiddenDefinition(ND, M);
+
+ if (getLangOpts().ModulesLocalVisibility)
+ MergedDefModules[ND].push_back(M);
+ else
+ ND->setHidden(false);
+}
+
+void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {
+ auto It = MergedDefModules.find(ND);
+ if (It == MergedDefModules.end())
+ return;
+
+ auto &Merged = It->second;
+ llvm::DenseSet<Module*> Found;
+ for (Module *&M : Merged)
+ if (!Found.insert(M).second)
+ M = nullptr;
+ Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end());
+}
+
+ExternCContextDecl *ASTContext::getExternCContextDecl() const {
+ if (!ExternCContext)
+ ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl());
+
+ return ExternCContext;
+}
+
RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
RecordDecl::TagKind TK) const {
SourceLocation Loc;
@@ -877,6 +909,8 @@ RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
NewDecl = RecordDecl::Create(*this, TK, getTranslationUnitDecl(), Loc, Loc,
&Idents.get(Name));
NewDecl->setImplicit();
+ NewDecl->addAttr(TypeVisibilityAttr::CreateImplicit(
+ const_cast<ASTContext &>(*this), TypeVisibilityAttr::Default));
return NewDecl;
}
@@ -1326,7 +1360,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
}
Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->hasGlobalStorage())
+ if (VD->hasGlobalStorage() && !ForAlignof)
Align = std::max(Align, getTargetInfo().getMinGlobalAlign());
}
}
@@ -1669,13 +1703,23 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
break;
}
- if (const EnumType *ET = dyn_cast<EnumType>(TT))
- return getTypeInfo(ET->getDecl()->getIntegerType());
+ if (const EnumType *ET = dyn_cast<EnumType>(TT)) {
+ const EnumDecl *ED = ET->getDecl();
+ TypeInfo Info =
+ getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType());
+ if (unsigned AttrAlign = ED->getMaxAlignment()) {
+ Info.Align = AttrAlign;
+ Info.AlignIsRequired = true;
+ }
+ return Info;
+ }
const RecordType *RT = cast<RecordType>(TT);
- const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl());
+ const RecordDecl *RD = RT->getDecl();
+ const ASTRecordLayout &Layout = getASTRecordLayout(RD);
Width = toBits(Layout.getSize());
Align = toBits(Layout.getAlignment());
+ AlignIsRequired = RD->hasAttr<AlignedAttr>();
break;
}
@@ -1778,13 +1822,20 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
TypeInfo TI = getTypeInfo(T);
unsigned ABIAlign = TI.Align;
+ T = T->getBaseElementTypeUnsafe();
+
+ // The preferred alignment of member pointers is that of a pointer.
+ if (T->isMemberPointerType())
+ return getPreferredTypeAlign(getPointerDiffType().getTypePtr());
+
if (Target->getTriple().getArch() == llvm::Triple::xcore)
return ABIAlign; // Never overalign on XCore.
// Double and long long should be naturally aligned if possible.
- T = T->getBaseElementTypeUnsafe();
if (const ComplexType *CT = T->getAs<ComplexType>())
T = CT->getElementType().getTypePtr();
+ if (const EnumType *ET = T->getAs<EnumType>())
+ T = ET->getDecl()->getIntegerType().getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
T->isSpecificBuiltinType(BuiltinType::LongLong) ||
T->isSpecificBuiltinType(BuiltinType::ULongLong))
@@ -1796,6 +1847,13 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
return ABIAlign;
}
+/// getTargetDefaultAlignForAttributeAligned - Return the default alignment
+/// for __attribute__((aligned)) on this target, to be used if no alignment
+/// value is specified.
+unsigned ASTContext::getTargetDefaultAlignForAttributeAligned(void) const {
+ return getTargetInfo().getDefaultAlignForAttributeAligned();
+}
+
/// getAlignOfGlobalVar - Return the alignment in bits that should be given
/// to a global variable of the specified type.
unsigned ASTContext::getAlignOfGlobalVar(QualType T) const {
@@ -3337,7 +3395,7 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
(void)CheckT;
}
- T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon);
+ T = new (*this, TypeAlignment) ElaboratedType(Keyword, NNS, NamedType, Canon);
Types.push_back(T);
ElaboratedTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3361,7 +3419,7 @@ ASTContext::getParenType(QualType InnerType) const {
(void)CheckT;
}
- T = new (*this) ParenType(InnerType, Canon);
+ T = new (*this, TypeAlignment) ParenType(InnerType, Canon);
Types.push_back(T);
ParenTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3390,7 +3448,7 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
if (T)
return QualType(T, 0);
- T = new (*this) DependentNameType(Keyword, NNS, Name, Canon);
+ T = new (*this, TypeAlignment) DependentNameType(Keyword, NNS, Name, Canon);
Types.push_back(T);
DependentNameTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3492,7 +3550,8 @@ QualType ASTContext::getPackExpansionType(QualType Pattern,
}
}
- T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions);
+ T = new (*this, TypeAlignment)
+ PackExpansionType(Pattern, Canon, NumExpansions);
Types.push_back(T);
PackExpansionTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -3500,9 +3559,9 @@ QualType ASTContext::getPackExpansionType(QualType Pattern,
/// CmpProtocolNames - Comparison predicate for sorting protocols
/// alphabetically.
-static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
- const ObjCProtocolDecl *RHS) {
- return LHS->getDeclName() < RHS->getDeclName();
+static int CmpProtocolNames(ObjCProtocolDecl *const *LHS,
+ ObjCProtocolDecl *const *RHS) {
+ return DeclarationName::compare((*LHS)->getDeclName(), (*RHS)->getDeclName());
}
static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
@@ -3513,7 +3572,7 @@ static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
return false;
for (unsigned i = 1; i != NumProtocols; ++i)
- if (!CmpProtocolNames(Protocols[i-1], Protocols[i]) ||
+ if (CmpProtocolNames(&Protocols[i - 1], &Protocols[i]) >= 0 ||
Protocols[i]->getCanonicalDecl() != Protocols[i])
return false;
return true;
@@ -3524,7 +3583,7 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
// Sort protocols, keyed by name.
- std::sort(Protocols, Protocols+NumProtocols, CmpProtocolNames);
+ llvm::array_pod_sort(Protocols, ProtocolsEnd, CmpProtocolNames);
// Canonicalize.
for (unsigned I = 0, N = NumProtocols; I != N; ++I)
@@ -4325,6 +4384,19 @@ QualType ASTContext::getSignatureParameterType(QualType T) const {
return T.getUnqualifiedType();
}
+QualType ASTContext::getExceptionObjectType(QualType T) const {
+ // C++ [except.throw]p3:
+ // A throw-expression initializes a temporary object, called the exception
+ // object, the type of which is determined by removing any top-level
+ // cv-qualifiers from the static type of the operand of throw and adjusting
+ // the type from "array of T" or "function returning T" to "pointer to T"
+ // or "pointer to function returning T", [...]
+ T = getVariableArrayDecayedType(T);
+ if (T->isArrayType() || T->isFunctionType())
+ T = getDecayedType(T);
+ return T.getUnqualifiedType();
+}
+
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
/// handling typedefs etc. The canonical type of "T" must be an array type,
@@ -4859,7 +4931,7 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const {
return getLangOpts().MSVCCompat && VD->isStaticDataMember() &&
VD->getType()->isIntegralOrEnumerationType() &&
- !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit();
+ VD->isFirstDecl() && !VD->isOutOfLine() && VD->hasInit();
}
static inline
@@ -7544,7 +7616,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
break;
case 'U':
assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
- assert(!Unsigned && "Can't use 'S' modifier multiple times!");
+ assert(!Unsigned && "Can't use 'U' modifier multiple times!");
Unsigned = true;
break;
case 'L':
@@ -7579,7 +7651,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
break;
case 'h':
assert(HowLong == 0 && !Signed && !Unsigned &&
- "Bad modifiers used with 'f'!");
+ "Bad modifiers used with 'h'!");
Type = Context.HalfTy;
break;
case 'f':
@@ -7806,6 +7878,9 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
ArgTypes.push_back(Ty);
}
+ if (Id == Builtin::BI__GetExceptionInfo)
+ return QualType();
+
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
"'.' should only occur at end of builtin type list!");
@@ -7909,7 +7984,7 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
while (LexicalContext && !isa<FunctionDecl>(LexicalContext))
LexicalContext = LexicalContext->getLexicalParent();
- // Let the static local variable inherit it's linkage from the nearest
+ // Let the static local variable inherit its linkage from the nearest
// enclosing function.
if (LexicalContext)
StaticLocalLinkage =
@@ -8042,7 +8117,9 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
if (IsCXXMethod)
return ABI->getDefaultMethodCallConv(IsVariadic);
- return (LangOpts.MRTD && !IsVariadic) ? CC_X86StdCall : CC_C;
+ if (LangOpts.MRTD && !IsVariadic) return CC_X86StdCall;
+
+ return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown);
}
bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
@@ -8161,6 +8238,31 @@ MangleNumberingContext *ASTContext::createMangleNumberingContext() const {
return ABI->createMangleNumberingContext();
}
+const CXXConstructorDecl *
+ASTContext::getCopyConstructorForExceptionObject(CXXRecordDecl *RD) {
+ return ABI->getCopyConstructorForExceptionObject(
+ cast<CXXRecordDecl>(RD->getFirstDecl()));
+}
+
+void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) {
+ return ABI->addCopyConstructorForExceptionObject(
+ cast<CXXRecordDecl>(RD->getFirstDecl()),
+ cast<CXXConstructorDecl>(CD->getFirstDecl()));
+}
+
+void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE) {
+ ABI->addDefaultArgExprForConstructor(
+ cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE);
+}
+
+Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx) {
+ return ABI->getDefaultArgExprForConstructor(
+ cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx);
+}
+
void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
ParamIndices[D] = index;
}
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index ebf5e651ef9a..60cbb0601138 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -508,6 +508,8 @@ namespace {
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
void VisitCXXConstructExpr(const CXXConstructExpr *Node);
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
+ void VisitCXXNewExpr(const CXXNewExpr *Node);
+ void VisitCXXDeleteExpr(const CXXDeleteExpr *Node);
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
void VisitExprWithCleanups(const ExprWithCleanups *Node);
void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
@@ -516,6 +518,7 @@ namespace {
VisitExpr(Node);
dumpDecl(Node->getLambdaClass());
}
+ void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
// ObjC
void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
@@ -974,8 +977,10 @@ void ASTDumper::dumpDecl(const Decl *D) {
dumpSourceRange(D->getSourceRange());
OS << ' ';
dumpLocation(D->getLocation());
- if (Module *M = D->getOwningModule())
+ if (Module *M = D->getImportedOwningModule())
OS << " in " << M->getFullModuleName();
+ else if (Module *M = D->getLocalOwningModule())
+ OS << " in (local) " << M->getFullModuleName();
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
if (ND->isHidden())
OS << " hidden";
@@ -1099,10 +1104,13 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
E = D->getDeclsInPrototypeScope().end(); I != E; ++I)
dumpDecl(*I);
- for (FunctionDecl::param_const_iterator I = D->param_begin(),
- E = D->param_end();
- I != E; ++I)
- dumpDecl(*I);
+ if (!D->param_begin() && D->getNumParams())
+ dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; });
+ else
+ for (FunctionDecl::param_const_iterator I = D->param_begin(),
+ E = D->param_end();
+ I != E; ++I)
+ dumpDecl(*I);
if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D))
for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
@@ -1913,6 +1921,32 @@ void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) {
dumpCXXTemporary(Node->getTemporary());
}
+void ASTDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
+ VisitExpr(Node);
+ if (Node->isGlobalNew())
+ OS << " global";
+ if (Node->isArray())
+ OS << " array";
+ if (Node->getOperatorNew()) {
+ OS << ' ';
+ dumpBareDeclRef(Node->getOperatorNew());
+ }
+ // We could dump the deallocation function used in case of error, but it's
+ // usually not that interesting.
+}
+
+void ASTDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
+ VisitExpr(Node);
+ if (Node->isGlobalDelete())
+ OS << " global";
+ if (Node->isArrayForm())
+ OS << " array";
+ if (Node->getOperatorDelete()) {
+ OS << ' ';
+ dumpBareDeclRef(Node->getOperatorDelete());
+ }
+}
+
void
ASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) {
VisitExpr(Node);
@@ -1934,6 +1968,13 @@ void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
OS << ")";
}
+void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
+ VisitExpr(Node);
+ dumpPointer(Node->getPack());
+ dumpName(Node->getPack());
+}
+
+
//===----------------------------------------------------------------------===//
// Obj-C Expressions
//===----------------------------------------------------------------------===//
@@ -2255,6 +2296,11 @@ LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
P.dumpStmt(this);
}
+LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const {
+ ASTDumper P(OS, nullptr, nullptr);
+ P.dumpStmt(this);
+}
+
LLVM_DUMP_METHOD void Stmt::dump() const {
ASTDumper P(llvm::errs(), nullptr, nullptr);
P.dumpStmt(this);
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 2442e8ec25f1..911f1681ce61 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -67,6 +67,7 @@ namespace clang {
// FIXME: DependentDecltypeType
QualType VisitRecordType(const RecordType *T);
QualType VisitEnumType(const EnumType *T);
+ QualType VisitAttributedType(const AttributedType *T);
// FIXME: TemplateTypeParmType
// FIXME: SubstTemplateTypeParmType
QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
@@ -80,7 +81,7 @@ namespace clang {
// Importing declarations
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
- SourceLocation &Loc);
+ NamedDecl *&ToD, SourceLocation &Loc);
void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
DeclarationNameInfo& To);
@@ -167,7 +168,44 @@ namespace clang {
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
// Importing statements
+ DeclGroupRef ImportDeclGroup(DeclGroupRef DG);
+
Stmt *VisitStmt(Stmt *S);
+ Stmt *VisitDeclStmt(DeclStmt *S);
+ Stmt *VisitNullStmt(NullStmt *S);
+ Stmt *VisitCompoundStmt(CompoundStmt *S);
+ Stmt *VisitCaseStmt(CaseStmt *S);
+ Stmt *VisitDefaultStmt(DefaultStmt *S);
+ Stmt *VisitLabelStmt(LabelStmt *S);
+ Stmt *VisitAttributedStmt(AttributedStmt *S);
+ Stmt *VisitIfStmt(IfStmt *S);
+ Stmt *VisitSwitchStmt(SwitchStmt *S);
+ Stmt *VisitWhileStmt(WhileStmt *S);
+ Stmt *VisitDoStmt(DoStmt *S);
+ Stmt *VisitForStmt(ForStmt *S);
+ Stmt *VisitGotoStmt(GotoStmt *S);
+ Stmt *VisitIndirectGotoStmt(IndirectGotoStmt *S);
+ Stmt *VisitContinueStmt(ContinueStmt *S);
+ Stmt *VisitBreakStmt(BreakStmt *S);
+ Stmt *VisitReturnStmt(ReturnStmt *S);
+ // FIXME: GCCAsmStmt
+ // FIXME: MSAsmStmt
+ // FIXME: SEHExceptStmt
+ // FIXME: SEHFinallyStmt
+ // FIXME: SEHTryStmt
+ // FIXME: SEHLeaveStmt
+ // FIXME: CapturedStmt
+ Stmt *VisitCXXCatchStmt(CXXCatchStmt *S);
+ Stmt *VisitCXXTryStmt(CXXTryStmt *S);
+ Stmt *VisitCXXForRangeStmt(CXXForRangeStmt *S);
+ // FIXME: MSDependentExistsStmt
+ Stmt *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
+ Stmt *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
+ Stmt *VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S);
+ Stmt *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
+ Stmt *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
+ Stmt *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
+ Stmt *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
// Importing expressions
Expr *VisitExpr(Expr *E);
@@ -181,6 +219,9 @@ namespace clang {
Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
+ Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
+ Expr *VisitMemberExpr(MemberExpr *E);
+ Expr *VisitCallExpr(CallExpr *E);
};
}
using namespace clang;
@@ -1724,6 +1765,27 @@ QualType ASTNodeImporter::VisitEnumType(const EnumType *T) {
return Importer.getToContext().getTagDeclType(ToDecl);
}
+QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
+ QualType FromModifiedType = T->getModifiedType();
+ QualType FromEquivalentType = T->getEquivalentType();
+ QualType ToModifiedType;
+ QualType ToEquivalentType;
+
+ if (!FromModifiedType.isNull()) {
+ ToModifiedType = Importer.Import(FromModifiedType);
+ if (ToModifiedType.isNull())
+ return QualType();
+ }
+ if (!FromEquivalentType.isNull()) {
+ ToEquivalentType = Importer.Import(FromEquivalentType);
+ if (ToEquivalentType.isNull())
+ return QualType();
+ }
+
+ return Importer.getToContext().getAttributedType(T->getAttrKind(),
+ ToModifiedType, ToEquivalentType);
+}
+
QualType ASTNodeImporter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
TemplateName ToTemplate = Importer.Import(T->getTemplateName());
@@ -1808,6 +1870,7 @@ ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC,
DeclarationName &Name,
+ NamedDecl *&ToD,
SourceLocation &Loc) {
// Import the context of this declaration.
DC = Importer.ImportContext(D->getDeclContext());
@@ -1828,6 +1891,7 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
// Import the location of this declaration.
Loc = Importer.Import(D->getLocation());
+ ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D));
return false;
}
@@ -2009,7 +2073,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To,
ImportDefinitionKind Kind) {
- if (To->getDefinition())
+ if (To->getAnyInitializer())
return false;
// FIXME: Can we really import any initializer? Alternatively, we could force
@@ -2239,8 +2303,11 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
NamespaceDecl *MergeWithNamespace = nullptr;
if (!Name) {
@@ -2307,8 +2374,11 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// If this typedef is not in block scope, determine whether we've
// seen a typedef with the same name (that we can merge with) or any
@@ -2381,8 +2451,11 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Figure out what enum name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
@@ -2466,8 +2539,11 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Figure out what structure name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
@@ -2592,8 +2668,11 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
QualType T = Importer.Import(D->getType());
if (T.isNull())
@@ -2648,8 +2727,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Try to find a function in our own ("to") context with the same name, same
// type, and in the same context as the function we're importing.
@@ -2741,10 +2823,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Create the imported function.
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
FunctionDecl *ToFunction = nullptr;
+ SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart());
if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
FromConstructor->isExplicit(),
D->isInlineSpecified(),
@@ -2753,7 +2836,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
} else if (isa<CXXDestructorDecl>(D)) {
ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
D->isInlineSpecified(),
D->isImplicit());
@@ -2761,7 +2844,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
= dyn_cast<CXXConversionDecl>(D)) {
ToFunction = CXXConversionDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
D->isInlineSpecified(),
FromConversion->isExplicit(),
@@ -2770,7 +2853,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
ToFunction = CXXMethodDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo,
Method->getStorageClass(),
Method->isInlineSpecified(),
@@ -2778,7 +2861,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
Importer.Import(D->getLocEnd()));
} else {
ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
- D->getInnerLocStart(),
+ InnerLocStart,
NameInfo, T, TInfo, D->getStorageClass(),
D->isInlineSpecified(),
D->hasWrittenPrototype(),
@@ -2809,6 +2892,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction->setType(T);
}
+ // Import the body, if any.
+ if (Stmt *FromBody = D->getBody()) {
+ if (Stmt *ToBody = Importer.Import(FromBody)) {
+ ToFunction->setBody(ToBody);
+ }
+ }
+
// FIXME: Other bits to merge?
// Add this function to the lexical context.
@@ -2855,8 +2945,11 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -2911,8 +3004,11 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -2978,8 +3074,11 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Determine whether we've already imported this ivar
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -3028,8 +3127,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Try to find a variable in our own ("to") context with the same name and
// in the same context as the variable we're importing.
@@ -3137,6 +3239,10 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
Importer.Imported(D, ToVar);
LexicalDC->addDeclInternal(ToVar);
+ if (!D->isFileVarDecl() &&
+ D->isUsed())
+ ToVar->setIsUsed();
+
// Merge the initializer.
if (ImportDefinition(D, ToVar))
return nullptr;
@@ -3196,6 +3302,10 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
T, TInfo, D->getStorageClass(),
/*FIXME: Default argument*/nullptr);
ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
+
+ if (D->isUsed())
+ ToParm->setIsUsed();
+
return Importer.Imported(D, ToParm);
}
@@ -3204,8 +3314,11 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
SmallVector<NamedDecl *, 2> FoundDecls;
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
@@ -3315,8 +3428,11 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
ObjCInterfaceDecl *ToInterface
= cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface()));
@@ -3439,8 +3555,11 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
ObjCProtocolDecl *MergeWithProtocol = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -3614,8 +3733,11 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Look for an existing interface with the same name.
ObjCInterfaceDecl *MergeWithIface = nullptr;
@@ -3769,8 +3891,11 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// Check whether we have already imported this property.
SmallVector<NamedDecl *, 2> FoundDecls;
@@ -4000,8 +4125,11 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// We may already have a template of the same name; try to find and match it.
if (!DC->isFunctionOrMethod()) {
@@ -4188,8 +4316,11 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ NamedDecl *ToD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return nullptr;
+ if (ToD)
+ return ToD;
// We may already have a template of the same name; try to find and match it.
assert(!DC->isFunctionOrMethod() &&
@@ -4371,10 +4502,457 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
// Import Statements
//----------------------------------------------------------------------------
-Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
- Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
- << S->getStmtClassName();
- return nullptr;
+DeclGroupRef ASTNodeImporter::ImportDeclGroup(DeclGroupRef DG) {
+ if (DG.isNull())
+ return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0);
+ size_t NumDecls = DG.end() - DG.begin();
+ SmallVector<Decl *, 1> ToDecls(NumDecls);
+ auto &_Importer = this->Importer;
+ std::transform(DG.begin(), DG.end(), ToDecls.begin(),
+ [&_Importer](Decl *D) -> Decl * {
+ return _Importer.Import(D);
+ });
+ return DeclGroupRef::Create(Importer.getToContext(),
+ ToDecls.begin(),
+ NumDecls);
+}
+
+ Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
+ Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
+ << S->getStmtClassName();
+ return nullptr;
+ }
+
+Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {
+ DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup());
+ for (Decl *ToD : ToDG) {
+ if (!ToD)
+ return nullptr;
+ }
+ SourceLocation ToStartLoc = Importer.Import(S->getStartLoc());
+ SourceLocation ToEndLoc = Importer.Import(S->getEndLoc());
+ return new (Importer.getToContext()) DeclStmt(ToDG, ToStartLoc, ToEndLoc);
+}
+
+Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
+ SourceLocation ToSemiLoc = Importer.Import(S->getSemiLoc());
+ return new (Importer.getToContext()) NullStmt(ToSemiLoc,
+ S->hasLeadingEmptyMacro());
+}
+
+Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
+ SmallVector<Stmt *, 4> ToStmts(S->size());
+ auto &_Importer = this->Importer;
+ std::transform(S->body_begin(), S->body_end(), ToStmts.begin(),
+ [&_Importer](Stmt *CS) -> Stmt * {
+ return _Importer.Import(CS);
+ });
+ for (Stmt *ToS : ToStmts) {
+ if (!ToS)
+ return nullptr;
+ }
+ SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
+ SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc());
+ return new (Importer.getToContext()) CompoundStmt(Importer.getToContext(),
+ ToStmts,
+ ToLBraceLoc, ToRBraceLoc);
+}
+
+Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
+ Expr *ToLHS = Importer.Import(S->getLHS());
+ if (!ToLHS)
+ return nullptr;
+ Expr *ToRHS = Importer.Import(S->getRHS());
+ if (!ToRHS && S->getRHS())
+ return nullptr;
+ SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc());
+ SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc());
+ SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
+ return new (Importer.getToContext()) CaseStmt(ToLHS, ToRHS,
+ ToCaseLoc, ToEllipsisLoc,
+ ToColonLoc);
+}
+
+Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {
+ SourceLocation ToDefaultLoc = Importer.Import(S->getDefaultLoc());
+ SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) DefaultStmt(ToDefaultLoc, ToColonLoc,
+ ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitLabelStmt(LabelStmt *S) {
+ SourceLocation ToIdentLoc = Importer.Import(S->getIdentLoc());
+ LabelDecl *ToLabelDecl =
+ cast_or_null<LabelDecl>(Importer.Import(S->getDecl()));
+ if (!ToLabelDecl && S->getDecl())
+ return nullptr;
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) LabelStmt(ToIdentLoc, ToLabelDecl,
+ ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) {
+ SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc());
+ ArrayRef<const Attr*> FromAttrs(S->getAttrs());
+ SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size());
+ ASTContext &_ToContext = Importer.getToContext();
+ std::transform(FromAttrs.begin(), FromAttrs.end(), ToAttrs.begin(),
+ [&_ToContext](const Attr *A) -> const Attr * {
+ return A->clone(_ToContext);
+ });
+ for (const Attr *ToA : ToAttrs) {
+ if (!ToA)
+ return nullptr;
+ }
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return AttributedStmt::Create(Importer.getToContext(), ToAttrLoc,
+ ToAttrs, ToSubStmt);
+}
+
+Stmt *ASTNodeImporter::VisitIfStmt(IfStmt *S) {
+ SourceLocation ToIfLoc = Importer.Import(S->getIfLoc());
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ Stmt *ToThenStmt = Importer.Import(S->getThen());
+ if (!ToThenStmt && S->getThen())
+ return nullptr;
+ SourceLocation ToElseLoc = Importer.Import(S->getElseLoc());
+ Stmt *ToElseStmt = Importer.Import(S->getElse());
+ if (!ToElseStmt && S->getElse())
+ return nullptr;
+ return new (Importer.getToContext()) IfStmt(Importer.getToContext(),
+ ToIfLoc, ToConditionVariable,
+ ToCondition, ToThenStmt,
+ ToElseLoc, ToElseStmt);
+}
+
+Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ SwitchStmt *ToStmt = new (Importer.getToContext()) SwitchStmt(
+ Importer.getToContext(), ToConditionVariable,
+ ToCondition);
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ ToStmt->setBody(ToBody);
+ ToStmt->setSwitchLoc(Importer.Import(S->getSwitchLoc()));
+ // Now we have to re-chain the cases.
+ SwitchCase *LastChainedSwitchCase = nullptr;
+ for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr;
+ SC = SC->getNextSwitchCase()) {
+ SwitchCase *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC));
+ if (!ToSC)
+ return nullptr;
+ if (LastChainedSwitchCase)
+ LastChainedSwitchCase->setNextSwitchCase(ToSC);
+ else
+ ToStmt->setSwitchCaseList(ToSC);
+ LastChainedSwitchCase = ToSC;
+ }
+ return ToStmt;
+}
+
+Stmt *ASTNodeImporter::VisitWhileStmt(WhileStmt *S) {
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc());
+ return new (Importer.getToContext()) WhileStmt(Importer.getToContext(),
+ ToConditionVariable,
+ ToCondition, ToBody,
+ ToWhileLoc);
+}
+
+Stmt *ASTNodeImporter::VisitDoStmt(DoStmt *S) {
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ SourceLocation ToDoLoc = Importer.Import(S->getDoLoc());
+ SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) DoStmt(ToBody, ToCondition,
+ ToDoLoc, ToWhileLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitForStmt(ForStmt *S) {
+ Stmt *ToInit = Importer.Import(S->getInit());
+ if (!ToInit && S->getInit())
+ return nullptr;
+ Expr *ToCondition = Importer.Import(S->getCond());
+ if (!ToCondition && S->getCond())
+ return nullptr;
+ VarDecl *ToConditionVariable = nullptr;
+ if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
+ ToConditionVariable =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
+ if (!ToConditionVariable)
+ return nullptr;
+ }
+ Expr *ToInc = Importer.Import(S->getInc());
+ if (!ToInc && S->getInc())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToLParenLoc = Importer.Import(S->getLParenLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) ForStmt(Importer.getToContext(),
+ ToInit, ToCondition,
+ ToConditionVariable,
+ ToInc, ToBody,
+ ToForLoc, ToLParenLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitGotoStmt(GotoStmt *S) {
+ LabelDecl *ToLabel = nullptr;
+ if (LabelDecl *FromLabel = S->getLabel()) {
+ ToLabel = dyn_cast_or_null<LabelDecl>(Importer.Import(FromLabel));
+ if (!ToLabel)
+ return nullptr;
+ }
+ SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc());
+ SourceLocation ToLabelLoc = Importer.Import(S->getLabelLoc());
+ return new (Importer.getToContext()) GotoStmt(ToLabel,
+ ToGotoLoc, ToLabelLoc);
+}
+
+Stmt *ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+ SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc());
+ SourceLocation ToStarLoc = Importer.Import(S->getStarLoc());
+ Expr *ToTarget = Importer.Import(S->getTarget());
+ if (!ToTarget && S->getTarget())
+ return nullptr;
+ return new (Importer.getToContext()) IndirectGotoStmt(ToGotoLoc, ToStarLoc,
+ ToTarget);
+}
+
+Stmt *ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) {
+ SourceLocation ToContinueLoc = Importer.Import(S->getContinueLoc());
+ return new (Importer.getToContext()) ContinueStmt(ToContinueLoc);
+}
+
+Stmt *ASTNodeImporter::VisitBreakStmt(BreakStmt *S) {
+ SourceLocation ToBreakLoc = Importer.Import(S->getBreakLoc());
+ return new (Importer.getToContext()) BreakStmt(ToBreakLoc);
+}
+
+Stmt *ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) {
+ SourceLocation ToRetLoc = Importer.Import(S->getReturnLoc());
+ Expr *ToRetExpr = Importer.Import(S->getRetValue());
+ if (!ToRetExpr && S->getRetValue())
+ return nullptr;
+ VarDecl *NRVOCandidate = const_cast<VarDecl*>(S->getNRVOCandidate());
+ VarDecl *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate));
+ if (!ToNRVOCandidate && NRVOCandidate)
+ return nullptr;
+ return new (Importer.getToContext()) ReturnStmt(ToRetLoc, ToRetExpr,
+ ToNRVOCandidate);
+}
+
+Stmt *ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ SourceLocation ToCatchLoc = Importer.Import(S->getCatchLoc());
+ VarDecl *ToExceptionDecl = nullptr;
+ if (VarDecl *FromExceptionDecl = S->getExceptionDecl()) {
+ ToExceptionDecl =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl));
+ if (!ToExceptionDecl)
+ return nullptr;
+ }
+ Stmt *ToHandlerBlock = Importer.Import(S->getHandlerBlock());
+ if (!ToHandlerBlock && S->getHandlerBlock())
+ return nullptr;
+ return new (Importer.getToContext()) CXXCatchStmt(ToCatchLoc,
+ ToExceptionDecl,
+ ToHandlerBlock);
+}
+
+Stmt *ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) {
+ SourceLocation ToTryLoc = Importer.Import(S->getTryLoc());
+ Stmt *ToTryBlock = Importer.Import(S->getTryBlock());
+ if (!ToTryBlock && S->getTryBlock())
+ return nullptr;
+ SmallVector<Stmt *, 1> ToHandlers(S->getNumHandlers());
+ for (unsigned HI = 0, HE = S->getNumHandlers(); HI != HE; ++HI) {
+ CXXCatchStmt *FromHandler = S->getHandler(HI);
+ if (Stmt *ToHandler = Importer.Import(FromHandler))
+ ToHandlers[HI] = ToHandler;
+ else
+ return nullptr;
+ }
+ return CXXTryStmt::Create(Importer.getToContext(), ToTryLoc, ToTryBlock,
+ ToHandlers);
+}
+
+Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
+ DeclStmt *ToRange =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt()));
+ if (!ToRange && S->getRangeStmt())
+ return nullptr;
+ DeclStmt *ToBeginEnd =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginEndStmt()));
+ if (!ToBeginEnd && S->getBeginEndStmt())
+ return nullptr;
+ Expr *ToCond = Importer.Import(S->getCond());
+ if (!ToCond && S->getCond())
+ return nullptr;
+ Expr *ToInc = Importer.Import(S->getInc());
+ if (!ToInc && S->getInc())
+ return nullptr;
+ DeclStmt *ToLoopVar =
+ dyn_cast_or_null<DeclStmt>(Importer.Import(S->getLoopVarStmt()));
+ if (!ToLoopVar && S->getLoopVarStmt())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) CXXForRangeStmt(ToRange, ToBeginEnd,
+ ToCond, ToInc,
+ ToLoopVar, ToBody,
+ ToForLoc, ToColonLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+ Stmt *ToElem = Importer.Import(S->getElement());
+ if (!ToElem && S->getElement())
+ return nullptr;
+ Expr *ToCollect = Importer.Import(S->getCollection());
+ if (!ToCollect && S->getCollection())
+ return nullptr;
+ Stmt *ToBody = Importer.Import(S->getBody());
+ if (!ToBody && S->getBody())
+ return nullptr;
+ SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ return new (Importer.getToContext()) ObjCForCollectionStmt(ToElem,
+ ToCollect,
+ ToBody, ToForLoc,
+ ToRParenLoc);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+ SourceLocation ToAtCatchLoc = Importer.Import(S->getAtCatchLoc());
+ SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
+ VarDecl *ToExceptionDecl = nullptr;
+ if (VarDecl *FromExceptionDecl = S->getCatchParamDecl()) {
+ ToExceptionDecl =
+ dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl));
+ if (!ToExceptionDecl)
+ return nullptr;
+ }
+ Stmt *ToBody = Importer.Import(S->getCatchBody());
+ if (!ToBody && S->getCatchBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtCatchStmt(ToAtCatchLoc,
+ ToRParenLoc,
+ ToExceptionDecl,
+ ToBody);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+ SourceLocation ToAtFinallyLoc = Importer.Import(S->getAtFinallyLoc());
+ Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyBody());
+ if (!ToAtFinallyStmt && S->getFinallyBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtFinallyStmt(ToAtFinallyLoc,
+ ToAtFinallyStmt);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+ SourceLocation ToAtTryLoc = Importer.Import(S->getAtTryLoc());
+ Stmt *ToAtTryStmt = Importer.Import(S->getTryBody());
+ if (!ToAtTryStmt && S->getTryBody())
+ return nullptr;
+ SmallVector<Stmt *, 1> ToCatchStmts(S->getNumCatchStmts());
+ for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) {
+ ObjCAtCatchStmt *FromCatchStmt = S->getCatchStmt(CI);
+ if (Stmt *ToCatchStmt = Importer.Import(FromCatchStmt))
+ ToCatchStmts[CI] = ToCatchStmt;
+ else
+ return nullptr;
+ }
+ Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyStmt());
+ if (!ToAtFinallyStmt && S->getFinallyStmt())
+ return nullptr;
+ return ObjCAtTryStmt::Create(Importer.getToContext(),
+ ToAtTryLoc, ToAtTryStmt,
+ ToCatchStmts.begin(), ToCatchStmts.size(),
+ ToAtFinallyStmt);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtSynchronizedStmt
+ (ObjCAtSynchronizedStmt *S) {
+ SourceLocation ToAtSynchronizedLoc =
+ Importer.Import(S->getAtSynchronizedLoc());
+ Expr *ToSynchExpr = Importer.Import(S->getSynchExpr());
+ if (!ToSynchExpr && S->getSynchExpr())
+ return nullptr;
+ Stmt *ToSynchBody = Importer.Import(S->getSynchBody());
+ if (!ToSynchBody && S->getSynchBody())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtSynchronizedStmt(
+ ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+ SourceLocation ToAtThrowLoc = Importer.Import(S->getThrowLoc());
+ Expr *ToThrow = Importer.Import(S->getThrowExpr());
+ if (!ToThrow && S->getThrowExpr())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAtThrowStmt(ToAtThrowLoc, ToThrow);
+}
+
+Stmt *ASTNodeImporter::VisitObjCAutoreleasePoolStmt
+ (ObjCAutoreleasePoolStmt *S) {
+ SourceLocation ToAtLoc = Importer.Import(S->getAtLoc());
+ Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
+ if (!ToSubStmt && S->getSubStmt())
+ return nullptr;
+ return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(ToAtLoc,
+ ToSubStmt);
}
//----------------------------------------------------------------------------
@@ -4585,6 +5163,107 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
Importer.Import(E->getRParenLoc()));
}
+Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ CXXConstructorDecl *ToCCD =
+ dyn_cast<CXXConstructorDecl>(Importer.Import(E->getConstructor()));
+ if (!ToCCD && E->getConstructor())
+ return nullptr;
+
+ size_t NumArgs = E->getNumArgs();
+ SmallVector<Expr *, 1> ToArgs(NumArgs);
+ ASTImporter &_Importer = Importer;
+ std::transform(E->arg_begin(), E->arg_end(), ToArgs.begin(),
+ [&_Importer](Expr *AE) -> Expr * {
+ return _Importer.Import(AE);
+ });
+ for (Expr *ToA : ToArgs) {
+ if (!ToA)
+ return nullptr;
+ }
+
+ return CXXConstructExpr::Create(Importer.getToContext(), T,
+ Importer.Import(E->getLocation()),
+ ToCCD, E->isElidable(),
+ ToArgs, E->hadMultipleCandidates(),
+ E->isListInitialization(),
+ E->isStdInitListInitialization(),
+ E->requiresZeroInitialization(),
+ E->getConstructionKind(),
+ Importer.Import(E->getParenOrBraceRange()));
+}
+
+Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToBase = Importer.Import(E->getBase());
+ if (!ToBase && E->getBase())
+ return nullptr;
+
+ ValueDecl *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl()));
+ if (!ToMember && E->getMemberDecl())
+ return nullptr;
+
+ DeclAccessPair ToFoundDecl = DeclAccessPair::make(
+ dyn_cast<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())),
+ E->getFoundDecl().getAccess());
+
+ DeclarationNameInfo ToMemberNameInfo(
+ Importer.Import(E->getMemberNameInfo().getName()),
+ Importer.Import(E->getMemberNameInfo().getLoc()));
+
+ if (E->hasExplicitTemplateArgs()) {
+ return nullptr; // FIXME: handle template arguments
+ }
+
+ return MemberExpr::Create(Importer.getToContext(), ToBase,
+ E->isArrow(),
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getQualifierLoc()),
+ Importer.Import(E->getTemplateKeywordLoc()),
+ ToMember, ToFoundDecl, ToMemberNameInfo,
+ nullptr, T, E->getValueKind(),
+ E->getObjectKind());
+}
+
+Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToCallee = Importer.Import(E->getCallee());
+ if (!ToCallee && E->getCallee())
+ return nullptr;
+
+ unsigned NumArgs = E->getNumArgs();
+
+ llvm::SmallVector<Expr *, 2> ToArgs(NumArgs);
+
+ for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) {
+ Expr *FromArg = E->getArg(ai);
+ Expr *ToArg = Importer.Import(FromArg);
+ if (!ToArg)
+ return nullptr;
+ ToArgs[ai] = ToArg;
+ }
+
+ Expr **ToArgs_Copied = new (Importer.getToContext())
+ Expr*[NumArgs];
+
+ for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai)
+ ToArgs_Copied[ai] = ToArgs[ai];
+
+ return new (Importer.getToContext())
+ CallExpr(Importer.getToContext(), ToCallee,
+ ArrayRef<Expr*>(ToArgs_Copied, NumArgs), T, E->getValueKind(),
+ Importer.Import(E->getRParenLoc()));
+}
+
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport)
@@ -4636,6 +5315,17 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
FromTSI->getTypeLoc().getLocStart());
}
+Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
+ llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
+ if (Pos != ImportedDecls.end()) {
+ Decl *ToD = Pos->second;
+ ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD);
+ return ToD;
+ } else {
+ return nullptr;
+ }
+}
+
Decl *ASTImporter::Import(Decl *FromD) {
if (!FromD)
return nullptr;
@@ -4927,8 +5617,9 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
FileID ToFileID = Import(Decomposed.first);
if (ToFileID.isInvalid())
return SourceLocation();
- return ToSM.getLocForStartOfFile(ToFileID)
- .getLocWithOffset(Decomposed.second);
+ SourceLocation ret = ToSM.getLocForStartOfFile(ToFileID)
+ .getLocWithOffset(Decomposed.second);
+ return ret;
}
SourceRange ASTImporter::Import(SourceRange FromRange) {
@@ -4952,7 +5643,7 @@ FileID ASTImporter::Import(FileID FromID) {
// Map the FileID for to the "to" source manager.
FileID ToID;
const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
- if (Cache->OrigEntry) {
+ if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
// disk again
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
index 0bf6bcd9092e..cb608700133c 100644
--- a/lib/AST/AttrImpl.cpp
+++ b/lib/AST/AttrImpl.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file contains out-of-line virtual methods for Attr classes.
+// This file contains out-of-line methods for Attr classes.
//
//===----------------------------------------------------------------------===//
@@ -18,10 +18,4 @@
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
-Attr::~Attr() { }
-
-void InheritableAttr::anchor() { }
-
-void InheritableParamAttr::anchor() { }
-
#include "clang/AST/AttrImpl.inc"
diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h
index 8e9e358525e8..dad226474fa7 100644
--- a/lib/AST/CXXABI.h
+++ b/lib/AST/CXXABI.h
@@ -20,6 +20,8 @@
namespace clang {
class ASTContext;
+class CXXConstructorDecl;
+class Expr;
class MemberPointerType;
class MangleNumberingContext;
@@ -41,6 +43,20 @@ public:
/// Returns a new mangling number context for this C++ ABI.
virtual MangleNumberingContext *createMangleNumberingContext() const = 0;
+
+ /// Adds a mapping from class to copy constructor for this C++ ABI.
+ virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *,
+ CXXConstructorDecl *) = 0;
+
+ /// Retrieves the mapping from class to copy constructor for this C++ ABI.
+ virtual const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0;
+
+ virtual void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE) = 0;
+
+ virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx) = 0;
};
/// Creates an instance of a C++ ABI class.
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 6e80ee7c28a1..800c8f83b880 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -318,48 +318,36 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
//
// FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy
// way to make it any faster.
- for (CXXBasePaths::paths_iterator P = Paths.begin(), PEnd = Paths.end();
- P != PEnd; /* increment in loop */) {
- bool Hidden = false;
-
- for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end();
- PE != PEEnd && !Hidden; ++PE) {
- if (PE->Base->isVirtual()) {
- CXXRecordDecl *VBase = nullptr;
- if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>())
- VBase = cast<CXXRecordDecl>(Record->getDecl());
- if (!VBase)
+ Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) {
+ for (const CXXBasePathElement &PE : Path) {
+ if (!PE.Base->isVirtual())
+ continue;
+
+ CXXRecordDecl *VBase = nullptr;
+ if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>())
+ VBase = cast<CXXRecordDecl>(Record->getDecl());
+ if (!VBase)
+ break;
+
+ // The declaration(s) we found along this path were found in a
+ // subobject of a virtual base. Check whether this virtual
+ // base is a subobject of any other path; if so, then the
+ // declaration in this path are hidden by that patch.
+ for (const CXXBasePath &HidingP : Paths) {
+ CXXRecordDecl *HidingClass = nullptr;
+ if (const RecordType *Record =
+ HidingP.back().Base->getType()->getAs<RecordType>())
+ HidingClass = cast<CXXRecordDecl>(Record->getDecl());
+ if (!HidingClass)
break;
- // The declaration(s) we found along this path were found in a
- // subobject of a virtual base. Check whether this virtual
- // base is a subobject of any other path; if so, then the
- // declaration in this path are hidden by that patch.
- for (CXXBasePaths::paths_iterator HidingP = Paths.begin(),
- HidingPEnd = Paths.end();
- HidingP != HidingPEnd;
- ++HidingP) {
- CXXRecordDecl *HidingClass = nullptr;
- if (const RecordType *Record
- = HidingP->back().Base->getType()->getAs<RecordType>())
- HidingClass = cast<CXXRecordDecl>(Record->getDecl());
- if (!HidingClass)
- break;
-
- if (HidingClass->isVirtuallyDerivedFrom(VBase)) {
- Hidden = true;
- break;
- }
- }
+ if (HidingClass->isVirtuallyDerivedFrom(VBase))
+ return true;
}
}
+ return false;
+ });
- if (Hidden)
- P = Paths.Paths.erase(P);
- else
- ++P;
- }
-
return true;
}
@@ -569,18 +557,14 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
// overrider. To do so, we dig down to the original virtual
// functions using data recursion and update all of the methods it
// overrides.
- typedef std::pair<CXXMethodDecl::method_iterator,
- CXXMethodDecl::method_iterator> OverriddenMethods;
+ typedef llvm::iterator_range<CXXMethodDecl::method_iterator>
+ OverriddenMethods;
SmallVector<OverriddenMethods, 4> Stack;
- Stack.push_back(std::make_pair(CanonM->begin_overridden_methods(),
- CanonM->end_overridden_methods()));
+ Stack.push_back(llvm::make_range(CanonM->begin_overridden_methods(),
+ CanonM->end_overridden_methods()));
while (!Stack.empty()) {
- OverriddenMethods OverMethods = Stack.back();
- Stack.pop_back();
-
- for (; OverMethods.first != OverMethods.second; ++OverMethods.first) {
- const CXXMethodDecl *CanonOM
- = cast<CXXMethodDecl>((*OverMethods.first)->getCanonicalDecl());
+ for (const CXXMethodDecl *OM : Stack.pop_back_val()) {
+ const CXXMethodDecl *CanonOM = OM->getCanonicalDecl();
// C++ [class.virtual]p2:
// A virtual member function C::vf of a class object S is
@@ -601,8 +585,8 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
// Continue recursion to the methods that this virtual method
// overrides.
- Stack.push_back(std::make_pair(CanonOM->begin_overridden_methods(),
- CanonOM->end_overridden_methods()));
+ Stack.push_back(llvm::make_range(CanonOM->begin_overridden_methods(),
+ CanonOM->end_overridden_methods()));
}
}
@@ -630,54 +614,32 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
// Weed out any final overriders that come from virtual base class
// subobjects that were hidden by other subobjects along any path.
// This is the final-overrider variant of C++ [class.member.lookup]p10.
- for (CXXFinalOverriderMap::iterator OM = FinalOverriders.begin(),
- OMEnd = FinalOverriders.end();
- OM != OMEnd;
- ++OM) {
- for (OverridingMethods::iterator SO = OM->second.begin(),
- SOEnd = OM->second.end();
- SO != SOEnd;
- ++SO) {
- SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO->second;
+ for (auto &OM : FinalOverriders) {
+ for (auto &SO : OM.second) {
+ SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO.second;
if (Overriding.size() < 2)
continue;
- for (SmallVectorImpl<UniqueVirtualMethod>::iterator
- Pos = Overriding.begin(), PosEnd = Overriding.end();
- Pos != PosEnd;
- /* increment in loop */) {
- if (!Pos->InVirtualSubobject) {
- ++Pos;
- continue;
- }
+ auto IsHidden = [&Overriding](const UniqueVirtualMethod &M) {
+ if (!M.InVirtualSubobject)
+ return false;
// We have an overriding method in a virtual base class
// subobject (or non-virtual base class subobject thereof);
// determine whether there exists an other overriding method
// in a base class subobject that hides the virtual base class
// subobject.
- bool Hidden = false;
- for (SmallVectorImpl<UniqueVirtualMethod>::iterator
- OP = Overriding.begin(), OPEnd = Overriding.end();
- OP != OPEnd && !Hidden;
- ++OP) {
- if (Pos == OP)
- continue;
-
- if (OP->Method->getParent()->isVirtuallyDerivedFrom(
- const_cast<CXXRecordDecl *>(Pos->InVirtualSubobject)))
- Hidden = true;
- }
-
- if (Hidden) {
- // The current overriding function is hidden by another
- // overriding function; remove this one.
- Pos = Overriding.erase(Pos);
- PosEnd = Overriding.end();
- } else {
- ++Pos;
- }
- }
+ for (const UniqueVirtualMethod &OP : Overriding)
+ if (&M != &OP &&
+ OP.Method->getParent()->isVirtuallyDerivedFrom(
+ M.InVirtualSubobject))
+ return true;
+ return false;
+ };
+
+ Overriding.erase(
+ std::remove_if(Overriding.begin(), Overriding.end(), IsHidden),
+ Overriding.end());
}
}
}
diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp
index 06a08bdad45f..98b7e367950c 100644
--- a/lib/AST/CommentLexer.cpp
+++ b/lib/AST/CommentLexer.cpp
@@ -514,6 +514,12 @@ void Lexer::lexVerbatimBlockBody(Token &T) {
if (CommentState == LCS_InsideCComment)
skipLineStartingDecorations();
+ if (BufferPtr == CommentEnd) {
+ formTokenWithChars(T, BufferPtr, tok::verbatim_block_line);
+ T.setVerbatimBlockText("");
+ return;
+ }
+
lexVerbatimBlockFirstLine(T);
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index dc08d23a24b5..8eff4c4427b3 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -44,6 +44,12 @@ bool Decl::isOutOfLine() const {
return !getLexicalDeclContext()->Equals(getDeclContext());
}
+TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
+ : Decl(TranslationUnit, nullptr, SourceLocation()),
+ DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {
+ Hidden = Ctx.getLangOpts().ModulesLocalVisibility;
+}
+
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
@@ -894,13 +900,13 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
// If the type of the function uses a type with unique-external
// linkage, it's not legally usable from outside this translation unit.
- // But only look at the type-as-written. If this function has an auto-deduced
- // return type, we can't compute the linkage of that type because it could
- // require looking at the linkage of this function, and we don't need this
- // for correctness because the type is not part of the function's
- // signature.
- // FIXME: This is a hack. We should be able to solve this circularity and the
- // one in getLVForNamespaceScopeDecl for Functions some other way.
+ // But only look at the type-as-written. If this function has an
+ // auto-deduced return type, we can't compute the linkage of that type
+ // because it could require looking at the linkage of this function, and we
+ // don't need this for correctness because the type is not part of the
+ // function's signature.
+ // FIXME: This is a hack. We should be able to solve this circularity and
+ // the one in getLVForNamespaceScopeDecl for Functions some other way.
{
QualType TypeAsWritten = MD->getType();
if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
@@ -1445,74 +1451,127 @@ void NamedDecl::getNameForDiagnostic(raw_ostream &OS,
printName(OS);
}
-bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
- assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
+static bool isKindReplaceableBy(Decl::Kind OldK, Decl::Kind NewK) {
+ // For method declarations, we never replace.
+ if (ObjCMethodDecl::classofKind(NewK))
+ return false;
- // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
- // We want to keep it, unless it nominates same namespace.
- if (getKind() == Decl::UsingDirective) {
- return cast<UsingDirectiveDecl>(this)->getNominatedNamespace()
- ->getOriginalNamespace() ==
- cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
- ->getOriginalNamespace();
+ if (OldK == NewK)
+ return true;
+
+ // A compatibility alias for a class can be replaced by an interface.
+ if (ObjCCompatibleAliasDecl::classofKind(OldK) &&
+ ObjCInterfaceDecl::classofKind(NewK))
+ return true;
+
+ // A typedef-declaration, alias-declaration, or Objective-C class declaration
+ // can replace another declaration of the same type. Semantic analysis checks
+ // that we have matching types.
+ if ((TypedefNameDecl::classofKind(OldK) ||
+ ObjCInterfaceDecl::classofKind(OldK)) &&
+ (TypedefNameDecl::classofKind(NewK) ||
+ ObjCInterfaceDecl::classofKind(NewK)))
+ return true;
+
+ // Otherwise, a kind mismatch implies that the declaration is not replaced.
+ return false;
+}
+
+template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) {
+ return true;
+}
+static bool isRedeclarableImpl(...) { return false; }
+static bool isRedeclarable(Decl::Kind K) {
+ switch (K) {
+#define DECL(Type, Base) \
+ case Decl::Type: \
+ return isRedeclarableImpl((Type##Decl *)nullptr);
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
}
+ llvm_unreachable("unknown decl kind");
+}
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
- // For function declarations, we keep track of redeclarations.
- return FD->getPreviousDecl() == OldD;
+bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
+ assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
- // For function templates, the underlying function declarations are linked.
- if (const FunctionTemplateDecl *FunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(this))
- if (const FunctionTemplateDecl *OldFunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(OldD))
- return FunctionTemplate->getTemplatedDecl()
- ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl());
-
- // For method declarations, we keep track of redeclarations.
- if (isa<ObjCMethodDecl>(this))
+ // Never replace one imported declaration with another; we need both results
+ // when re-exporting.
+ if (OldD->isFromASTFile() && isFromASTFile())
return false;
- // FIXME: Is this correct if one of the decls comes from an inline namespace?
- if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD))
- return true;
+ if (!isKindReplaceableBy(OldD->getKind(), getKind()))
+ return false;
- if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD))
- return cast<UsingShadowDecl>(this)->getTargetDecl() ==
- cast<UsingShadowDecl>(OldD)->getTargetDecl();
+ // Inline namespaces can give us two declarations with the same
+ // name and kind in the same scope but different contexts; we should
+ // keep both declarations in this case.
+ if (!this->getDeclContext()->getRedeclContext()->Equals(
+ OldD->getDeclContext()->getRedeclContext()))
+ return false;
- if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD)) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
+ // For function declarations, we keep track of redeclarations.
+ // FIXME: This returns false for functions that should in fact be replaced.
+ // Instead, perform some kind of type check?
+ if (FD->getPreviousDecl() != OldD)
+ return false;
+
+ // For function templates, the underlying function declarations are linked.
+ if (const FunctionTemplateDecl *FunctionTemplate =
+ dyn_cast<FunctionTemplateDecl>(this))
+ return FunctionTemplate->getTemplatedDecl()->declarationReplaces(
+ cast<FunctionTemplateDecl>(OldD)->getTemplatedDecl());
+
+ // Using shadow declarations can be overloaded on their target declarations
+ // if they introduce functions.
+ // FIXME: If our target replaces the old target, can we replace the old
+ // shadow declaration?
+ if (auto *USD = dyn_cast<UsingShadowDecl>(this))
+ if (USD->getTargetDecl() != cast<UsingShadowDecl>(OldD)->getTargetDecl())
+ return false;
+
+ // Using declarations can be overloaded if they introduce functions.
+ if (auto *UD = dyn_cast<UsingDecl>(this)) {
ASTContext &Context = getASTContext();
- return Context.getCanonicalNestedNameSpecifier(
- cast<UsingDecl>(this)->getQualifier()) ==
+ return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
Context.getCanonicalNestedNameSpecifier(
- cast<UsingDecl>(OldD)->getQualifier());
+ cast<UsingDecl>(OldD)->getQualifier());
}
-
- if (isa<UnresolvedUsingValueDecl>(this) &&
- isa<UnresolvedUsingValueDecl>(OldD)) {
+ if (auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) {
ASTContext &Context = getASTContext();
- return Context.getCanonicalNestedNameSpecifier(
- cast<UnresolvedUsingValueDecl>(this)->getQualifier()) ==
+ return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) ==
Context.getCanonicalNestedNameSpecifier(
cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
}
- // A typedef of an Objective-C class type can replace an Objective-C class
- // declaration or definition, and vice versa.
- // FIXME: Is this correct if one of the decls comes from an inline namespace?
- if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) ||
- (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD)))
- return true;
+ // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
+ // We want to keep it, unless it nominates same namespace.
+ if (auto *UD = dyn_cast<UsingDirectiveDecl>(this))
+ return UD->getNominatedNamespace()->getOriginalNamespace() ==
+ cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
+ ->getOriginalNamespace();
+
+ if (!IsKnownNewer && isRedeclarable(getKind())) {
+ // Check whether this is actually newer than OldD. We want to keep the
+ // newer declaration. This loop will usually only iterate once, because
+ // OldD is usually the previous declaration.
+ for (auto D : redecls()) {
+ if (D == OldD)
+ break;
- // For non-function declarations, if the declarations are of the
- // same kind and have the same parent then this must be a redeclaration,
- // or semantic analysis would not have given us the new declaration.
- // Note that inline namespaces can give us two declarations with the same
- // name and kind in the same scope but different contexts.
- return this->getKind() == OldD->getKind() &&
- this->getDeclContext()->getRedeclContext()->Equals(
- OldD->getDeclContext()->getRedeclContext());
+ // If we reach the canonical declaration, then OldD is not actually older
+ // than this one.
+ //
+ // FIXME: In this case, we should not add this decl to the lookup table.
+ if (D->isCanonicalDecl())
+ return false;
+ }
+ }
+
+ // It's a newer declaration of the same kind of declaration in the same scope,
+ // and not an overload: we want this decl instead of the existing one.
+ return true;
}
bool NamedDecl::hasLinkage() const {
@@ -1684,8 +1743,7 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
if (NumTPLists > 0) {
TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
NumTemplParamLists = NumTPLists;
- for (unsigned i = NumTPLists; i-- > 0; )
- TemplParamLists[i] = TPLists[i];
+ std::copy(TPLists, TPLists + NumTPLists, TemplParamLists);
}
}
@@ -1717,6 +1775,8 @@ VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC,
"VarDeclBitfields too large!");
static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned),
"ParmVarDeclBitfields too large!");
+ static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned),
+ "NonParmVarDeclBitfields too large!");
AllBits = 0;
VarDeclBits.SClass = SC;
// Everything else is implicitly initialized to false.
@@ -1743,9 +1803,12 @@ void VarDecl::setStorageClass(StorageClass SC) {
VarDecl::TLSKind VarDecl::getTLSKind() const {
switch (VarDeclBits.TSCSpec) {
case TSCS_unspecified:
- if (hasAttr<ThreadAttr>())
- return TLS_Static;
- return TLS_None;
+ if (!hasAttr<ThreadAttr>())
+ return TLS_None;
+ return getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2015)
+ ? TLS_Dynamic
+ : TLS_Static;
case TSCS___thread: // Fall through.
case TSCS__Thread_local:
return TLS_Static;
@@ -1825,9 +1888,8 @@ bool VarDecl::isInExternCXXContext() const {
VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }
-VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
- ASTContext &C) const
-{
+VarDecl::DefinitionKind
+VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
// C++ [basic.def]p2:
// A declaration is a definition unless [...] it contains the 'extern'
// specifier or a linkage-specification and neither an initializer [...],
@@ -1867,6 +1929,10 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
if (hasAttr<AliasAttr>())
return Definition;
+ if (const auto *SAA = getAttr<SelectAnyAttr>())
+ if (!SAA->isInherited())
+ return Definition;
+
// A variable template specialization (other than a static data member
// template or an explicit specialization) is a declaration until we
// instantiate its initializer.
@@ -2460,39 +2526,6 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace();
}
-FunctionDecl *
-FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const {
- ASTContext &Ctx = getASTContext();
- if (!Ctx.getLangOpts().SizedDeallocation)
- return nullptr;
-
- if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
- return nullptr;
- if (getDeclName().getCXXOverloadedOperator() != OO_Delete &&
- getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
- return nullptr;
- if (isa<CXXRecordDecl>(getDeclContext()))
- return nullptr;
-
- if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
- return nullptr;
-
- if (getNumParams() != 2 || isVariadic() ||
- !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getParamType(1),
- Ctx.getSizeType()))
- return nullptr;
-
- // This is a sized deallocation function. Find the corresponding unsized
- // deallocation function.
- lookup_const_result R = getDeclContext()->lookup(getDeclName());
- for (lookup_const_result::iterator RI = R.begin(), RE = R.end(); RI != RE;
- ++RI)
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI))
- if (FD->getNumParams() == 1 && !FD->isVariadic())
- return FD;
- return nullptr;
-}
-
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
return getDeclLanguageLinkage(*this);
}
@@ -2550,10 +2583,6 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
IsInline = true;
}
-const FunctionDecl *FunctionDecl::getCanonicalDecl() const {
- return getFirstDecl();
-}
-
FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
/// \brief Returns a value indicating whether this function
@@ -2581,7 +2610,14 @@ unsigned FunctionDecl::getBuiltinID() const {
// extern "C".
// FIXME: A recognised library function may not be directly in an extern "C"
// declaration, for instance "extern "C" { namespace std { decl } }".
- if (!LinkageDecl || LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
+ if (!LinkageDecl) {
+ if (BuiltinID == Builtin::BI__GetExceptionInfo &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ isInStdNamespace())
+ return Builtin::BI__GetExceptionInfo;
+ return 0;
+ }
+ if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
return 0;
}
@@ -2796,6 +2832,18 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const {
return RTRange;
}
+bool FunctionDecl::hasUnusedResultAttr() const {
+ QualType RetType = getReturnType();
+ if (RetType->isRecordType()) {
+ const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
+ const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this);
+ if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() &&
+ !(MD && MD->getCorrespondingMethodInClass(Ret, true)))
+ return true;
+ }
+ return hasAttr<WarnUnusedResultAttr>();
+}
+
/// \brief For an inline function definition in C, or for a gnu_inline function
/// in C++, determine whether the definition will be externally visible.
///
@@ -3077,6 +3125,8 @@ DependentFunctionTemplateSpecializationInfo::
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
const TemplateArgumentListInfo &TArgs)
: AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
+ static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
+ "Trailing data is unaligned!");
d.NumTemplates = Ts.size();
d.NumArgs = TArgs.size();
@@ -3590,7 +3640,7 @@ void RecordDecl::completeDefinition() {
/// This which can be turned on with an attribute, pragma, or the
/// -mms-bitfields command-line option.
bool RecordDecl::isMsStruct(const ASTContext &C) const {
- return hasAttr<MsStructAttr>() || C.getLangOpts().MSBitfields == 1;
+ return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1;
}
static bool isFieldOrIndirectField(Decl::Kind K) {
@@ -3747,6 +3797,13 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
}
+void ExternCContextDecl::anchor() { }
+
+ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
+ TranslationUnitDecl *DC) {
+ return new (C, DC) ExternCContextDecl(DC);
+}
+
void LabelDecl::anchor() { }
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
@@ -3885,6 +3942,21 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
void TypedefNameDecl::anchor() { }
+TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
+ if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) {
+ auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl();
+ auto *ThisTypedef = this;
+ if (AnyRedecl && OwningTypedef) {
+ OwningTypedef = OwningTypedef->getCanonicalDecl();
+ ThisTypedef = ThisTypedef->getCanonicalDecl();
+ }
+ if (OwningTypedef == ThisTypedef)
+ return TT->getDecl();
+ }
+
+ return nullptr;
+}
+
TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr);
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index a46787fb0e8f..79cadcfcb167 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -66,6 +66,12 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context,
void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
DeclContext *Parent, std::size_t Extra) {
assert(!Parent || &Parent->getParentASTContext() == &Ctx);
+ // With local visibility enabled, we track the owning module even for local
+ // declarations.
+ if (Ctx.getLangOpts().ModulesLocalVisibility) {
+ void *Buffer = ::operator new(sizeof(Module *) + Size + Extra, Ctx);
+ return new (Buffer) Module*(nullptr) + 1;
+ }
return ::operator new(Size + Extra, Ctx);
}
@@ -336,20 +342,34 @@ bool Decl::isReferenced() const {
static AvailabilityResult CheckAvailability(ASTContext &Context,
const AvailabilityAttr *A,
std::string *Message) {
- StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
- StringRef PrettyPlatformName
- = AvailabilityAttr::getPrettyPlatformName(TargetPlatform);
- if (PrettyPlatformName.empty())
- PrettyPlatformName = TargetPlatform;
+ VersionTuple TargetMinVersion =
+ Context.getTargetInfo().getPlatformMinVersion();
- VersionTuple TargetMinVersion = Context.getTargetInfo().getPlatformMinVersion();
if (TargetMinVersion.empty())
return AR_Available;
+ // Check if this is an App Extension "platform", and if so chop off
+ // the suffix for matching with the actual platform.
+ StringRef ActualPlatform = A->getPlatform()->getName();
+ StringRef RealizedPlatform = ActualPlatform;
+ if (Context.getLangOpts().AppExt) {
+ size_t suffix = RealizedPlatform.rfind("_app_extension");
+ if (suffix != StringRef::npos)
+ RealizedPlatform = RealizedPlatform.slice(0, suffix);
+ }
+
+ StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
+
// Match the platform name.
- if (A->getPlatform()->getName() != TargetPlatform)
+ if (RealizedPlatform != TargetPlatform)
return AR_Available;
-
+
+ StringRef PrettyPlatformName
+ = AvailabilityAttr::getPrettyPlatformName(ActualPlatform);
+
+ if (PrettyPlatformName.empty())
+ PrettyPlatformName = ActualPlatform;
+
std::string HintMessage;
if (!A->getMessage().empty()) {
HintMessage = " - ";
@@ -583,6 +603,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Block:
case Captured:
case TranslationUnit:
+ case ExternCContext:
case UsingDirective:
case ClassTemplateSpecialization:
@@ -846,6 +867,10 @@ bool DeclContext::isDependentContext() const {
return getLexicalParent()->isDependentContext();
}
+ // FIXME: A variable template is a dependent context, but is not a
+ // DeclContext. A context within it (such as a lambda-expression)
+ // should be considered dependent.
+
return getParent() && getParent()->isDependentContext();
}
@@ -889,6 +914,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const {
DeclContext *DeclContext::getPrimaryContext() {
switch (DeclKind) {
case Decl::TranslationUnit:
+ case Decl::ExternCContext:
case Decl::LinkageSpec:
case Decl::Block:
case Decl::Captured:
@@ -991,23 +1017,24 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls,
/// built a lookup map. For every name in the map, pull in the new names from
/// the external storage.
void DeclContext::reconcileExternalVisibleStorage() const {
- assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer());
+ assert(NeedToReconcileExternalVisibleStorage && LookupPtr);
NeedToReconcileExternalVisibleStorage = false;
- for (auto &Lookup : *LookupPtr.getPointer())
+ for (auto &Lookup : *LookupPtr)
Lookup.second.setHasExternalDecls();
}
/// \brief Load the declarations within this lexical storage from an
/// external source.
-void
+/// \return \c true if any declarations were added.
+bool
DeclContext::LoadLexicalDeclsFromExternalStorage() const {
ExternalASTSource *Source = getParentASTContext().getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
// Notify that we have a DeclContext that is initializing.
ExternalASTSource::Deserializing ADeclContext(Source);
-
+
// Load the external declarations, if any.
SmallVector<Decl*, 64> Decls;
ExternalLexicalStorage = false;
@@ -1017,11 +1044,11 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
case ELR_Failure:
case ELR_AlreadyLoaded:
- return;
+ return false;
}
if (Decls.empty())
- return;
+ return false;
// We may have already loaded just the fields of this record, in which case
// we need to ignore them.
@@ -1038,6 +1065,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
FirstDecl = ExternalFirst;
if (!LastDecl)
LastDecl = ExternalLast;
+ return true;
}
DeclContext::lookup_result
@@ -1045,7 +1073,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name) {
ASTContext &Context = DC->getParentASTContext();
StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr.getPointer()))
+ if (!(Map = DC->LookupPtr))
Map = DC->CreateStoredDeclsMap(Context);
if (DC->NeedToReconcileExternalVisibleStorage)
DC->reconcileExternalVisibleStorage();
@@ -1061,7 +1089,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
ArrayRef<NamedDecl*> Decls) {
ASTContext &Context = DC->getParentASTContext();
StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr.getPointer()))
+ if (!(Map = DC->LookupPtr))
Map = DC->CreateStoredDeclsMap(Context);
if (DC->NeedToReconcileExternalVisibleStorage)
DC->reconcileExternalVisibleStorage();
@@ -1078,7 +1106,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
// first.
llvm::SmallVector<unsigned, 8> Skip;
for (unsigned I = 0, N = Decls.size(); I != N; ++I)
- if (List.HandleRedeclaration(Decls[I]))
+ if (List.HandleRedeclaration(Decls[I], /*IsKnownNewer*/false))
Skip.push_back(I);
Skip.push_back(Decls.size());
@@ -1155,7 +1183,7 @@ void DeclContext::removeDecl(Decl *D) {
// Remove only decls that have a name
if (!ND->getDeclName()) return;
- StoredDeclsMap *Map = getPrimaryContext()->LookupPtr.getPointer();
+ StoredDeclsMap *Map = getPrimaryContext()->LookupPtr;
if (!Map) return;
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
@@ -1243,32 +1271,38 @@ static bool shouldBeHidden(NamedDecl *D) {
StoredDeclsMap *DeclContext::buildLookup() {
assert(this == getPrimaryContext() && "buildLookup called on non-primary DC");
- // FIXME: Should we keep going if hasExternalVisibleStorage?
- if (!LookupPtr.getInt())
- return LookupPtr.getPointer();
+ if (!HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups)
+ return LookupPtr;
SmallVector<DeclContext *, 2> Contexts;
collectAllContexts(Contexts);
- for (unsigned I = 0, N = Contexts.size(); I != N; ++I)
- buildLookupImpl<&DeclContext::decls_begin,
- &DeclContext::decls_end>(Contexts[I]);
+
+ if (HasLazyExternalLexicalLookups) {
+ HasLazyExternalLexicalLookups = false;
+ for (auto *DC : Contexts) {
+ if (DC->hasExternalLexicalStorage())
+ HasLazyLocalLexicalLookups |=
+ DC->LoadLexicalDeclsFromExternalStorage();
+ }
+
+ if (!HasLazyLocalLexicalLookups)
+ return LookupPtr;
+ }
+
+ for (auto *DC : Contexts)
+ buildLookupImpl(DC, hasExternalVisibleStorage());
// We no longer have any lazy decls.
- LookupPtr.setInt(false);
- return LookupPtr.getPointer();
+ HasLazyLocalLexicalLookups = false;
+ return LookupPtr;
}
/// buildLookupImpl - Build part of the lookup data structure for the
/// declarations contained within DCtx, which will either be this
/// DeclContext, a DeclContext linked to it, or a transparent context
/// nested within it.
-template<DeclContext::decl_iterator (DeclContext::*Begin)() const,
- DeclContext::decl_iterator (DeclContext::*End)() const>
-void DeclContext::buildLookupImpl(DeclContext *DCtx) {
- for (decl_iterator I = (DCtx->*Begin)(), E = (DCtx->*End)();
- I != E; ++I) {
- Decl *D = *I;
-
+void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
+ for (Decl *D : DCtx->noload_decls()) {
// Insert this declaration into the lookup structure, but only if
// it's semantically within its decl context. Any other decls which
// should be found in this context are added eagerly.
@@ -1282,39 +1316,46 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx) {
(!ND->isFromASTFile() ||
(isTranslationUnit() &&
!getParentASTContext().getLangOpts().CPlusPlus)))
- makeDeclVisibleInContextImpl(ND, false);
+ makeDeclVisibleInContextImpl(ND, Internal);
// If this declaration is itself a transparent declaration context
// or inline namespace, add the members of this declaration of that
// context (recursively).
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D))
if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
- buildLookupImpl<Begin, End>(InnerCtx);
+ buildLookupImpl(InnerCtx, Internal);
}
}
+NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr;
+
DeclContext::lookup_result
-DeclContext::lookup(DeclarationName Name) {
+DeclContext::lookup(DeclarationName Name) const {
assert(DeclKind != Decl::LinkageSpec &&
"Should not perform lookups into linkage specs!");
- DeclContext *PrimaryContext = getPrimaryContext();
+ const DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
return PrimaryContext->lookup(Name);
- // If this is a namespace, ensure that any later redeclarations of it have
- // been loaded, since they may add names to the result of this lookup.
- if (auto *ND = dyn_cast<NamespaceDecl>(this))
- (void)ND->getMostRecentDecl();
+ // If we have an external source, ensure that any later redeclarations of this
+ // context have been loaded, since they may add names to the result of this
+ // lookup (or add external visible storage).
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ if (Source)
+ (void)cast<Decl>(this)->getMostRecentDecl();
if (hasExternalVisibleStorage()) {
+ assert(Source && "external visible storage but no external source?");
+
if (NeedToReconcileExternalVisibleStorage)
reconcileExternalVisibleStorage();
- StoredDeclsMap *Map = LookupPtr.getPointer();
+ StoredDeclsMap *Map = LookupPtr;
- if (LookupPtr.getInt())
- Map = buildLookup();
+ if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
+ // FIXME: Make buildLookup const?
+ Map = const_cast<DeclContext*>(this)->buildLookup();
if (!Map)
Map = CreateStoredDeclsMap(getParentASTContext());
@@ -1325,28 +1366,27 @@ DeclContext::lookup(DeclarationName Name) {
if (!R.second && !R.first->second.hasExternalDecls())
return R.first->second.getLookupResult();
- ExternalASTSource *Source = getParentASTContext().getExternalSource();
if (Source->FindExternalVisibleDeclsByName(this, Name) || !R.second) {
- if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ if (StoredDeclsMap *Map = LookupPtr) {
StoredDeclsMap::iterator I = Map->find(Name);
if (I != Map->end())
return I->second.getLookupResult();
}
}
- return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
+ return lookup_result();
}
- StoredDeclsMap *Map = LookupPtr.getPointer();
- if (LookupPtr.getInt())
- Map = buildLookup();
+ StoredDeclsMap *Map = LookupPtr;
+ if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
+ Map = const_cast<DeclContext*>(this)->buildLookup();
if (!Map)
- return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
+ return lookup_result();
StoredDeclsMap::iterator I = Map->find(Name);
if (I == Map->end())
- return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
+ return lookup_result();
return I->second.getLookupResult();
}
@@ -1355,40 +1395,29 @@ DeclContext::lookup_result
DeclContext::noload_lookup(DeclarationName Name) {
assert(DeclKind != Decl::LinkageSpec &&
"Should not perform lookups into linkage specs!");
- if (!hasExternalVisibleStorage())
- return lookup(Name);
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
return PrimaryContext->noload_lookup(Name);
- StoredDeclsMap *Map = LookupPtr.getPointer();
- if (LookupPtr.getInt()) {
- // Carefully build the lookup map, without deserializing anything.
+ // If we have any lazy lexical declarations not in our lookup map, add them
+ // now. Don't import any external declarations, not even if we know we have
+ // some missing from the external visible lookups.
+ if (HasLazyLocalLexicalLookups) {
SmallVector<DeclContext *, 2> Contexts;
collectAllContexts(Contexts);
for (unsigned I = 0, N = Contexts.size(); I != N; ++I)
- buildLookupImpl<&DeclContext::noload_decls_begin,
- &DeclContext::noload_decls_end>(Contexts[I]);
-
- // We no longer have any lazy decls.
- LookupPtr.setInt(false);
-
- // There may now be names for which we have local decls but are
- // missing the external decls. FIXME: Just set the hasExternalDecls
- // flag on those names that have external decls.
- NeedToReconcileExternalVisibleStorage = true;
-
- Map = LookupPtr.getPointer();
+ buildLookupImpl(Contexts[I], hasExternalVisibleStorage());
+ HasLazyLocalLexicalLookups = false;
}
+ StoredDeclsMap *Map = LookupPtr;
if (!Map)
- return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr));
+ return lookup_result();
StoredDeclsMap::iterator I = Map->find(Name);
return I != Map->end() ? I->second.getLookupResult()
- : lookup_result(lookup_iterator(nullptr),
- lookup_iterator(nullptr));
+ : lookup_result();
}
void DeclContext::localUncachedLookup(DeclarationName Name,
@@ -1404,8 +1433,9 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
}
// If we have a lookup table, check there first. Maybe we'll get lucky.
- if (Name && !LookupPtr.getInt()) {
- if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ // FIXME: Should we be checking these flags on the primary context?
+ if (Name && !HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) {
+ if (StoredDeclsMap *Map = LookupPtr) {
StoredDeclsMap::iterator Pos = Map->find(Name);
if (Pos != Map->end()) {
Results.insert(Results.end(),
@@ -1418,6 +1448,8 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
// Slow case: grovel through the declarations in our chain looking for
// matches.
+ // FIXME: If we have lazy external declarations, this will not find them!
+ // FIXME: Should we CollectAllContexts and walk them all here?
for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
if (ND->getDeclName() == Name)
@@ -1498,7 +1530,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
// FIXME: As a performance hack, don't add such decls into the translation
// unit unless we're in C++, since qualified lookup into the TU is never
// performed.
- if (LookupPtr.getPointer() || hasExternalVisibleStorage() ||
+ if (LookupPtr || hasExternalVisibleStorage() ||
((!Recoverable || D->getDeclContext() != D->getLexicalDeclContext()) &&
(getParentASTContext().getLangOpts().CPlusPlus ||
!isTranslationUnit()))) {
@@ -1508,7 +1540,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
buildLookup();
makeDeclVisibleInContextImpl(D, Internal);
} else {
- LookupPtr.setInt(true);
+ HasLazyLocalLexicalLookups = true;
}
// If we are a transparent context or inline namespace, insert into our
@@ -1526,7 +1558,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
// Find or create the stored declaration map.
- StoredDeclsMap *Map = LookupPtr.getPointer();
+ StoredDeclsMap *Map = LookupPtr;
if (!Map) {
ASTContext *C = &getParentASTContext();
Map = CreateStoredDeclsMap(*C);
@@ -1555,12 +1587,12 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
return;
}
- else if (DeclNameEntries.isNull()) {
+ if (DeclNameEntries.isNull()) {
DeclNameEntries.setOnlyValue(D);
return;
}
- if (DeclNameEntries.HandleRedeclaration(D)) {
+ if (DeclNameEntries.HandleRedeclaration(D, /*IsKnownNewer*/!Internal)) {
// This declaration has replaced an existing one for which
// declarationReplaces returns true.
return;
@@ -1570,15 +1602,17 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
DeclNameEntries.AddSubsequentDecl(D);
}
+UsingDirectiveDecl *DeclContext::udir_iterator::operator*() const {
+ return cast<UsingDirectiveDecl>(*I);
+}
+
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
/// this context.
DeclContext::udir_range DeclContext::using_directives() const {
// FIXME: Use something more efficient than normal lookup for using
// directives. In C++, using directives are looked up more than anything else.
- lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
- return udir_range(
- reinterpret_cast<UsingDirectiveDecl *const *>(Result.begin()),
- reinterpret_cast<UsingDirectiveDecl *const *>(Result.end()));
+ lookup_result Result = lookup(UsingDirectiveDecl::getName());
+ return udir_range(Result.begin(), Result.end());
}
//===----------------------------------------------------------------------===//
@@ -1586,7 +1620,7 @@ DeclContext::udir_range DeclContext::using_directives() const {
//===----------------------------------------------------------------------===//
StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
- assert(!LookupPtr.getPointer() && "context already has a decls map");
+ assert(!LookupPtr && "context already has a decls map");
assert(getPrimaryContext() == this &&
"creating decls map on non-primary context");
@@ -1598,7 +1632,7 @@ StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
M = new StoredDeclsMap();
M->Previous = C.LastSDM;
C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent);
- LookupPtr.setPointer(M);
+ LookupPtr = M;
return M;
}
@@ -1630,11 +1664,11 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
assert(Parent->isDependentContext()
&& "cannot iterate dependent diagnostics of non-dependent context");
Parent = Parent->getPrimaryContext();
- if (!Parent->LookupPtr.getPointer())
+ if (!Parent->LookupPtr)
Parent->CreateStoredDeclsMap(C);
- DependentStoredDeclsMap *Map
- = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr.getPointer());
+ DependentStoredDeclsMap *Map =
+ static_cast<DependentStoredDeclsMap *>(Parent->LookupPtr);
// Allocate the copy of the PartialDiagnostic via the ASTContext's
// BumpPtrAllocator, rather than the ASTContext itself.
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 9af8c4b242a6..8dc62dd07f2c 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -991,7 +991,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
if (!isLambda()) return nullptr;
DeclarationName Name =
getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
- DeclContext::lookup_const_result Calls = lookup(Name);
+ DeclContext::lookup_result Calls = lookup(Name);
assert(!Calls.empty() && "Missing lambda call operator!");
assert(Calls.size() == 1 && "More than one lambda call operator!");
@@ -1008,7 +1008,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
if (!isLambda()) return nullptr;
DeclarationName Name =
&getASTContext().Idents.get(getLambdaStaticInvokerName());
- DeclContext::lookup_const_result Invoker = lookup(Name);
+ DeclContext::lookup_result Invoker = lookup(Name);
if (Invoker.empty()) return nullptr;
assert(Invoker.size() == 1 && "More than one static invoker operator!");
NamedDecl *InvokerFun = Invoker.front();
@@ -1173,7 +1173,7 @@ static void CollectVisibleConversions(ASTContext &Context,
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
-std::pair<CXXRecordDecl::conversion_iterator,CXXRecordDecl::conversion_iterator>
+llvm::iterator_range<CXXRecordDecl::conversion_iterator>
CXXRecordDecl::getVisibleConversionFunctions() {
ASTContext &Ctx = getASTContext();
@@ -1189,7 +1189,7 @@ CXXRecordDecl::getVisibleConversionFunctions() {
data().ComputedVisibleConversions = true;
}
}
- return std::make_pair(Set->begin(), Set->end());
+ return llvm::make_range(Set->begin(), Set->end());
}
void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) {
@@ -1307,7 +1307,7 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
= Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(ClassType));
- DeclContext::lookup_const_result R = lookup(Name);
+ DeclContext::lookup_result R = lookup(Name);
if (R.empty())
return nullptr;
@@ -1418,9 +1418,8 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
return nullptr;
}
- lookup_const_result Candidates = RD->lookup(getDeclName());
- for (NamedDecl * const * I = Candidates.begin(); I != Candidates.end(); ++I) {
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*I);
+ for (auto *ND : RD->lookup(getDeclName())) {
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND);
if (!MD)
continue;
if (recursivelyOverrides(MD, this))
@@ -1491,8 +1490,8 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
// This function is a usual deallocation function if there are no
// single-parameter deallocation functions of the same kind.
- DeclContext::lookup_const_result R = getDeclContext()->lookup(getDeclName());
- for (DeclContext::lookup_const_result::iterator I = R.begin(), E = R.end();
+ DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName());
+ for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
I != E; ++I) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I))
if (FD->getNumParams() == 1)
@@ -1740,6 +1739,10 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isImplicitlyDeclared, isConstexpr);
}
+CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
+ return CtorInitializers.get(getASTContext().getExternalSource());
+}
+
CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
assert(isDelegatingConstructor() && "Not a delegating constructor!");
Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
@@ -1887,6 +1890,15 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isInline, isImplicitlyDeclared);
}
+void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD) {
+ auto *First = cast<CXXDestructorDecl>(getFirstDecl());
+ if (OD && !First->OperatorDelete) {
+ First->OperatorDelete = OD;
+ if (auto *L = getASTMutationListener())
+ L->ResolvedOperatorDelete(First, OD);
+ }
+}
+
void CXXConversionDecl::anchor() { }
CXXConversionDecl *
diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp
index 9861f2278f9a..512837fdf3f4 100644
--- a/lib/AST/DeclGroup.cpp
+++ b/lib/AST/DeclGroup.cpp
@@ -18,6 +18,8 @@
using namespace clang;
DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+ static_assert(sizeof(DeclGroup) % llvm::AlignOf<void *>::Alignment == 0,
+ "Trailing data is unaligned!");
assert(NumDecls > 1 && "Invalid DeclGroup");
unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index ed5367514c30..a63ba7e698a8 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -54,8 +54,8 @@ void ObjCContainerDecl::anchor() { }
///
ObjCIvarDecl *
ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
- lookup_const_result R = lookup(Id);
- for (lookup_const_iterator Ivar = R.begin(), IvarEnd = R.end();
+ lookup_result R = lookup(Id);
+ for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end();
Ivar != IvarEnd; ++Ivar) {
if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
return ivar;
@@ -83,8 +83,8 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
// + (float) class_method;
// @end
//
- lookup_const_result R = lookup(Sel);
- for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end();
+ lookup_result R = lookup(Sel);
+ for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
Meth != MethEnd; ++Meth) {
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
if (MD && MD->isInstanceMethod() == isInstance)
@@ -101,8 +101,8 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
const ObjCPropertyDecl *Property) const {
Selector Sel = Property->getSetterName();
- lookup_const_result R = lookup(Sel);
- for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end();
+ lookup_result R = lookup(Sel);
+ for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
Meth != MethEnd; ++Meth) {
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
if (MD && MD->isInstanceMethod() && !MD->isImplicit())
@@ -161,8 +161,8 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
return nullptr;
}
- DeclContext::lookup_const_result R = DC->lookup(propertyID);
- for (DeclContext::lookup_const_iterator I = R.begin(), E = R.end(); I != E;
+ DeclContext::lookup_result R = DC->lookup(propertyID);
+ for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I)
if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I))
return PD;
@@ -334,9 +334,8 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
return;
// Merge ProtocolRefs into class's protocol list;
- for (auto *P : all_referenced_protocols()) {
- ProtocolRefs.push_back(P);
- }
+ ProtocolRefs.append(all_referenced_protocol_begin(),
+ all_referenced_protocol_end());
data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
}
@@ -617,8 +616,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
// Look through local category implementations associated with the class.
if (!Method)
- Method = Instance ? getCategoryInstanceMethod(Sel)
- : getCategoryClassMethod(Sel);
+ Method = getCategoryMethod(Sel, Instance);
// Before we give up, check if the selector is an instance method.
// But only in the root. This matches gcc's behavior and what the
@@ -1101,7 +1099,7 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
if (NumArgs > 1)
return nullptr;
- if (!isInstanceMethod() || getMethodFamily() != OMF_None)
+ if (!isInstanceMethod())
return nullptr;
if (isPropertyAccessor()) {
@@ -1822,6 +1820,11 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
}
}
+ObjCImplementationDecl::init_const_iterator
+ObjCImplementationDecl::init_begin() const {
+ return IvarInitializers.get(getASTContext().getExternalSource());
+}
+
raw_ostream &clang::operator<<(raw_ostream &OS,
const ObjCImplementationDecl &ID) {
OS << ID.getName();
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 0d1d2a4613dc..6374a92621a4 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -160,17 +160,43 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
return Common;
}
-template <class EntryType>
-typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType*
+template<class EntryType>
+typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
RedeclarableTemplateDecl::findSpecializationImpl(
- llvm::FoldingSetVector<EntryType> &Specs,
- ArrayRef<TemplateArgument> Args,
- void *&InsertPos) {
+ llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args,
+ void *&InsertPos) {
typedef SpecEntryTraits<EntryType> SETraits;
llvm::FoldingSetNodeID ID;
EntryType::Profile(ID,Args, getASTContext());
EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
- return Entry ? SETraits::getMostRecentDecl(Entry) : nullptr;
+ return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
+}
+
+template<class Derived, class EntryType>
+void RedeclarableTemplateDecl::addSpecializationImpl(
+ llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
+ void *InsertPos) {
+ typedef SpecEntryTraits<EntryType> SETraits;
+ if (InsertPos) {
+#ifndef NDEBUG
+ void *CorrectInsertPos;
+ assert(!findSpecializationImpl(Specializations,
+ SETraits::getTemplateArgs(Entry),
+ CorrectInsertPos) &&
+ InsertPos == CorrectInsertPos &&
+ "given incorrect InsertPos for specialization");
+#endif
+ Specializations.InsertNode(Entry, InsertPos);
+ } else {
+ EntryType *Existing = Specializations.GetOrInsertNode(Entry);
+ (void)Existing;
+ assert(SETraits::getDecl(Existing)->isCanonicalDecl() &&
+ "non-canonical specialization?");
+ }
+
+ if (ASTMutationListener *L = getASTMutationListener())
+ L->AddedCXXTemplateSpecialization(cast<Derived>(this),
+ SETraits::getDecl(Entry));
}
/// \brief Generate the injected template arguments for the given template
@@ -246,7 +272,11 @@ FunctionTemplateDecl::newCommon(ASTContext &C) const {
}
void FunctionTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
@@ -270,12 +300,8 @@ FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void FunctionTemplateDecl::addSpecialization(
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
- if (InsertPos)
- getSpecializations().InsertNode(Info, InsertPos);
- else
- getSpecializations().GetOrInsertNode(Info);
- if (ASTMutationListener *L = getASTMutationListener())
- L->AddedCXXTemplateSpecialization(this, Info->Function);
+ addSpecializationImpl<FunctionTemplateDecl>(getSpecializations(), Info,
+ InsertPos);
}
ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() {
@@ -320,7 +346,11 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
}
void ClassTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
@@ -357,16 +387,7 @@ ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
void *InsertPos) {
- if (InsertPos)
- getSpecializations().InsertNode(D, InsertPos);
- else {
- ClassTemplateSpecializationDecl *Existing
- = getSpecializations().GetOrInsertNode(D);
- (void)Existing;
- assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
- }
- if (ASTMutationListener *L = getASTMutationListener())
- L->AddedCXXTemplateSpecialization(this, D);
+ addSpecializationImpl<ClassTemplateDecl>(getSpecializations(), D, InsertPos);
}
ClassTemplatePartialSpecializationDecl *
@@ -953,7 +974,11 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
// TODO: Unify across class, function and variable templates?
// May require moving this and Common to RedeclarableTemplateDecl.
void VarTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
@@ -990,16 +1015,7 @@ VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
void *InsertPos) {
- if (InsertPos)
- getSpecializations().InsertNode(D, InsertPos);
- else {
- VarTemplateSpecializationDecl *Existing =
- getSpecializations().GetOrInsertNode(D);
- (void)Existing;
- assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
- }
- if (ASTMutationListener *L = getASTMutationListener())
- L->AddedCXXTemplateSpecialization(this, D);
+ addSpecializationImpl<VarTemplateDecl>(getSpecializations(), D, InsertPos);
}
VarTemplatePartialSpecializationDecl *
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 712de5056e8d..76a4da2371b5 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1141,40 +1141,13 @@ CallExpr::CallExpr(const ASTContext& C, StmtClass SC, Expr *fn,
RParenLoc = rparenloc;
}
-CallExpr::CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args,
+CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args,
QualType t, ExprValueKind VK, SourceLocation rparenloc)
- : Expr(CallExprClass, t, VK, OK_Ordinary,
- fn->isTypeDependent(),
- fn->isValueDependent(),
- fn->isInstantiationDependent(),
- fn->containsUnexpandedParameterPack()),
- NumArgs(args.size()) {
-
- SubExprs = new (C) Stmt*[args.size()+PREARGS_START];
- SubExprs[FN] = fn;
- for (unsigned i = 0; i != args.size(); ++i) {
- if (args[i]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (args[i]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (args[i]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (args[i]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
- SubExprs[i+PREARGS_START] = args[i];
- }
-
- CallExprBits.NumPreArgs = 0;
- RParenLoc = rparenloc;
+ : CallExpr(C, CallExprClass, fn, /*NumPreArgs=*/0, args, t, VK, rparenloc) {
}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) {
- // FIXME: Why do we allocate this?
- SubExprs = new (C) Stmt*[PREARGS_START];
- CallExprBits.NumPreArgs = 0;
-}
+ : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
EmptyShell Empty)
@@ -1271,16 +1244,21 @@ bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const {
return false;
}
-QualType CallExpr::getCallReturnType() const {
- QualType CalleeType = getCallee()->getType();
- if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>())
+QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const {
+ const Expr *Callee = getCallee();
+ QualType CalleeType = Callee->getType();
+ if (const auto *FnTypePtr = CalleeType->getAs<PointerType>()) {
CalleeType = FnTypePtr->getPointeeType();
- else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>())
+ } else if (const auto *BPT = CalleeType->getAs<BlockPointerType>()) {
CalleeType = BPT->getPointeeType();
- else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember))
+ } else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
+ if (isa<CXXPseudoDestructorExpr>(Callee->IgnoreParens()))
+ return Ctx.VoidTy;
+
// This should never be overloaded and so should never return null.
- CalleeType = Expr::findBoundMemberType(getCallee());
-
+ CalleeType = Expr::findBoundMemberType(Callee);
+ }
+
const FunctionType *FnType = CalleeType->castAs<FunctionType>();
return FnType->getReturnType();
}
@@ -1360,16 +1338,50 @@ IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const {
return reinterpret_cast<IdentifierInfo *> (Data & ~(uintptr_t)Mask);
}
-MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *memberdecl,
- DeclAccessPair founddecl,
- DeclarationNameInfo nameinfo,
- const TemplateArgumentListInfo *targs,
- QualType ty,
- ExprValueKind vk,
- ExprObjectKind ok) {
+UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTrait ExprKind, Expr *E, QualType resultType,
+ SourceLocation op, SourceLocation rp)
+ : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
+ false, // Never type-dependent (C++ [temp.dep.expr]p3).
+ // Value-dependent if the argument is type-dependent.
+ E->isTypeDependent(), E->isInstantiationDependent(),
+ E->containsUnexpandedParameterPack()),
+ OpLoc(op), RParenLoc(rp) {
+ UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
+ UnaryExprOrTypeTraitExprBits.IsType = false;
+ Argument.Ex = E;
+
+ // Check to see if we are in the situation where alignof(decl) should be
+ // dependent because decl's alignment is dependent.
+ if (ExprKind == UETT_AlignOf) {
+ if (!isValueDependent() || !isInstantiationDependent()) {
+ E = E->IgnoreParens();
+
+ const ValueDecl *D = nullptr;
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ D = DRE->getDecl();
+ else if (const auto *ME = dyn_cast<MemberExpr>(E))
+ D = ME->getMemberDecl();
+
+ if (D) {
+ for (const auto *I : D->specific_attrs<AlignedAttr>()) {
+ if (I->isAlignmentDependent()) {
+ setValueDependent(true);
+ setInstantiationDependent(true);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+MemberExpr *MemberExpr::Create(
+ const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ ValueDecl *memberdecl, DeclAccessPair founddecl,
+ DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs,
+ QualType ty, ExprValueKind vk, ExprObjectKind ok) {
std::size_t Size = sizeof(MemberExpr);
bool hasQualOrFound = (QualifierLoc ||
@@ -1384,8 +1396,8 @@ MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow,
Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
- MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo,
- ty, vk, ok);
+ MemberExpr *E = new (Mem)
+ MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok);
if (hasQualOrFound) {
// FIXME: Wrong. We should be looking at the member declaration we found.
@@ -2132,8 +2144,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case OO_Greater:
case OO_GreaterEqual:
case OO_LessEqual:
- if (Op->getCallReturnType()->isReferenceType() ||
- Op->getCallReturnType()->isVoidType())
+ if (Op->getCallReturnType(Ctx)->isReferenceType() ||
+ Op->getCallReturnType(Ctx)->isVoidType())
break;
WarnE = this;
Loc = Op->getOperatorLoc();
@@ -2149,12 +2161,16 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
if (const Decl *FD = CE->getCalleeDecl()) {
+ const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
+ bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr()
+ : FD->hasAttr<WarnUnusedResultAttr>();
+
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
//
// Note: If new cases are added here, DiagnoseUnusedExprResult should be
// updated to match for QoI.
- if (FD->hasAttr<WarnUnusedResultAttr>() ||
+ if (HasWarnUnusedResultAttr ||
FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) {
WarnE = this;
Loc = CE->getCallee()->getLocStart();
@@ -2200,9 +2216,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
}
if (const ObjCMethodDecl *MD = ME->getMethodDecl())
- if (MD->hasAttr<WarnUnusedResultAttr>() ||
- (MD->isPropertyAccessor() && !MD->getReturnType()->isVoidType() &&
- !ME->getReceiverType()->isObjCIdType())) {
+ if (MD->hasAttr<WarnUnusedResultAttr>()) {
WarnE = this;
Loc = getExprLoc();
return true;
@@ -2387,7 +2401,7 @@ QualType Expr::findBoundMemberType(const Expr *expr) {
return type;
}
- assert(isa<UnresolvedMemberExpr>(expr));
+ assert(isa<UnresolvedMemberExpr>(expr) || isa<CXXPseudoDestructorExpr>(expr));
return QualType();
}
@@ -2932,11 +2946,19 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass:
case CUDAKernelCallExprClass:
+ case UserDefinedLiteralClass: {
+ // We don't know a call definitely has side effects, except for calls
+ // to pure/const functions that definitely don't.
+ // If the call itself is considered side-effect free, check the operands.
+ const Decl *FD = cast<CallExpr>(this)->getCalleeDecl();
+ bool IsPure = FD && (FD->hasAttr<ConstAttr>() || FD->hasAttr<PureAttr>());
+ if (IsPure || !IncludePossibleEffects)
+ break;
+ return true;
+ }
+
case BlockExprClass:
case CXXBindTemporaryExprClass:
- case UserDefinedLiteralClass:
- // We don't know a call definitely has side effects, but we can check the
- // call's operands.
if (!IncludePossibleEffects)
break;
return true;
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 93361666183b..d6f2ce63a0a5 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -208,8 +208,9 @@ void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray,
}
bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const {
- return getOperatorNew()->getType()->
- castAs<FunctionProtoType>()->isNothrow(Ctx);
+ return getOperatorNew()->getType()->castAs<FunctionProtoType>()->isNothrow(
+ Ctx) &&
+ !getOperatorNew()->isReservedGlobalPlacementOperator();
}
// CXXDeleteExpr
@@ -237,10 +238,7 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
SourceLocation ColonColonLoc, SourceLocation TildeLoc,
PseudoDestructorTypeStorage DestroyedType)
: Expr(CXXPseudoDestructorExprClass,
- Context.getPointerType(Context.getFunctionType(
- Context.VoidTy, None,
- FunctionProtoType::ExtProtoInfo(
- Context.getDefaultCallingConvention(false, true)))),
+ Context.BoundMemberTy,
VK_RValue, OK_Ordinary,
/*isTypeDependent=*/(Base->isTypeDependent() ||
(DestroyedType.getTypeSourceInfo() &&
@@ -359,8 +357,7 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
Results = static_cast<DeclAccessPair *>(
C.Allocate(sizeof(DeclAccessPair) * NumResults,
llvm::alignOf<DeclAccessPair>()));
- memcpy(Results, &*Begin.getIterator(),
- NumResults * sizeof(DeclAccessPair));
+ memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
// If we have explicit template arguments, check for dependent
@@ -401,8 +398,7 @@ void OverloadExpr::initializeResults(const ASTContext &C,
C.Allocate(sizeof(DeclAccessPair) * NumResults,
llvm::alignOf<DeclAccessPair>()));
- memcpy(Results, &*Begin.getIterator(),
- NumResults * sizeof(DeclAccessPair));
+ memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
}
@@ -1031,6 +1027,11 @@ LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0);
}
+bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
+ return (C->capturesVariable() && C->getCapturedVar()->isInitCapture() &&
+ (getCallOperator() == C->getCapturedVar()->getDeclContext()));
+}
+
LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
return getLambdaClass()->getLambdaData().Captures;
}
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 933ea97fa2ba..5b320c2694ab 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -283,7 +283,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CXXMemberCallExprClass:
case Expr::UserDefinedLiteralClass:
case Expr::CUDAKernelCallExprClass:
- return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType());
+ return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType(Ctx));
// __builtin_choose_expr is equivalent to the chosen expression.
case Expr::ChooseExprClass:
@@ -418,9 +418,10 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
islvalue = NTTParm->getType()->isReferenceType();
else
islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
- isa<IndirectFieldDecl>(D) ||
- (Ctx.getLangOpts().CPlusPlus &&
- (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)));
+ isa<IndirectFieldDecl>(D) ||
+ (Ctx.getLangOpts().CPlusPlus &&
+ (isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) ||
+ isa<FunctionTemplateDecl>(D)));
return islvalue ? Cl::CL_LValue : Cl::CL_PRValue;
}
@@ -605,7 +606,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
if (CT.isConstQualified())
return Cl::CM_ConstQualified;
if (CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant)
- return Cl::CM_ConstQualified;
+ return Cl::CM_ConstAddrSpace;
// Arrays are not modifiable, only their elements are.
if (CT->isArrayType())
@@ -671,6 +672,7 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
llvm_unreachable("CM_LValueCast and CL_LValue don't match");
case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty;
case Cl::CM_ConstQualified: return MLV_ConstQualified;
+ case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace;
case Cl::CM_ArrayType: return MLV_ArrayType;
case Cl::CM_IncompleteType: return MLV_IncompleteType;
}
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 3d7f2dca7a2f..d1ec7aea1d2a 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1406,7 +1406,7 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
return true;
}
-const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
+static const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
return LVal.Base.dyn_cast<const ValueDecl*>();
}
@@ -2173,7 +2173,7 @@ struct CompleteObject {
assert(Value && "missing value for complete object");
}
- LLVM_EXPLICIT operator bool() const { return Value; }
+ explicit operator bool() const { return Value; }
};
/// Find the designated sub-object of an rvalue.
@@ -2502,8 +2502,9 @@ static bool AreElementsOfSameArray(QualType ObjType,
}
/// Find the complete object to which an LValue refers.
-CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK,
- const LValue &LVal, QualType LValType) {
+static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
+ AccessKinds AK, const LValue &LVal,
+ QualType LValType) {
if (!LVal.Base) {
Info.Diag(E, diag::note_constexpr_access_null) << AK;
return CompleteObject();
@@ -3726,8 +3727,9 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
// Skip this for non-union classes with no fields; in that case, the defaulted
// copy/move does not actually read the object.
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee);
- if (MD && MD->isDefaulted() && MD->isTrivial() &&
- (MD->getParent()->isUnion() || hasFields(MD->getParent()))) {
+ if (MD && MD->isDefaulted() &&
+ (MD->getParent()->isUnion() ||
+ (MD->isTrivial() && hasFields(MD->getParent())))) {
assert(This &&
(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
LValue RHS;
@@ -3791,11 +3793,9 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
// Skip this for empty non-union classes; we should not perform an
// lvalue-to-rvalue conversion on them because their copy constructor does not
// actually read them.
- if (Definition->isDefaulted() &&
- ((Definition->isCopyConstructor() && Definition->isTrivial()) ||
- (Definition->isMoveConstructor() && Definition->isTrivial())) &&
+ if (Definition->isDefaulted() && Definition->isCopyOrMoveConstructor() &&
(Definition->getParent()->isUnion() ||
- hasFields(Definition->getParent()))) {
+ (Definition->isTrivial() && hasFields(Definition->getParent())))) {
LValue RHS;
RHS.setFrom(Info.Ctx, ArgValues[0]);
return handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(),
@@ -6834,7 +6834,7 @@ void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) {
}
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->isAssignmentOp())
+ if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp())
return Error(E);
if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E))
@@ -6846,7 +6846,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) {
ComplexValue LHS, RHS;
bool LHSOK;
- if (E->getLHS()->getType()->isRealFloatingType()) {
+ if (E->isAssignmentOp()) {
+ LValue LV;
+ EvaluateLValue(E->getLHS(), LV, Info);
+ LHSOK = false;
+ } else if (LHSTy->isRealFloatingType()) {
LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info);
if (LHSOK) {
LHS.makeComplexFloat();
@@ -7586,10 +7590,23 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context,
else if (S->getString().getAsInteger(0, fill))
return false;
- if (SNaN)
- Result = llvm::APFloat::getSNaN(Sem, false, &fill);
- else
- Result = llvm::APFloat::getQNaN(Sem, false, &fill);
+ if (Context.getTargetInfo().isNan2008()) {
+ if (SNaN)
+ Result = llvm::APFloat::getSNaN(Sem, false, &fill);
+ else
+ Result = llvm::APFloat::getQNaN(Sem, false, &fill);
+ } else {
+ // Prior to IEEE 754-2008, architectures were allowed to choose whether
+ // the first bit of their significand was set for qNaN or sNaN. MIPS chose
+ // a different encoding to what became a standard in 2008, and for pre-
+ // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
+ // sNaN. This is now known as "legacy NaN" encoding.
+ if (SNaN)
+ Result = llvm::APFloat::getQNaN(Sem, false, &fill);
+ else
+ Result = llvm::APFloat::getSNaN(Sem, false, &fill);
+ }
+
return true;
}
diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp
index 88941075dd06..730842a28f6a 100644
--- a/lib/AST/ExternalASTSource.cpp
+++ b/lib/AST/ExternalASTSource.cpp
@@ -66,6 +66,11 @@ Stmt *ExternalASTSource::GetExternalDeclStmt(uint64_t Offset) {
return nullptr;
}
+CXXCtorInitializer **
+ExternalASTSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
+ return nullptr;
+}
+
CXXBaseSpecifier *
ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
return nullptr;
diff --git a/lib/AST/InheritViz.cpp b/lib/AST/InheritViz.cpp
index eb3020c5f518..0b82da133fa7 100644
--- a/lib/AST/InheritViz.cpp
+++ b/lib/AST/InheritViz.cpp
@@ -22,11 +22,9 @@
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <set>
+using namespace clang;
-using namespace llvm;
-
-namespace clang {
-
+namespace {
/// InheritanceHierarchyWriter - Helper class that writes out a
/// GraphViz file that diagrams the inheritance hierarchy starting at
/// a given C++ class type. Note that we do not use LLVM's
@@ -44,7 +42,8 @@ public:
: Context(Context), Out(Out) { }
void WriteGraph(QualType Type) {
- Out << "digraph \"" << DOT::EscapeString(Type.getAsString()) << "\" {\n";
+ Out << "digraph \"" << llvm::DOT::EscapeString(Type.getAsString())
+ << "\" {\n";
WriteNode(Type, false);
Out << "}\n";
}
@@ -59,6 +58,7 @@ protected:
/// (only) virtual base.
raw_ostream& WriteNodeReference(QualType Type, bool FromVirtual);
};
+} // namespace
void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
QualType CanonType = Context.getCanonicalType(Type);
@@ -78,7 +78,7 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
// Give the node a label based on the name of the class.
std::string TypeName = Type.getAsString();
- Out << " [ shape=\"box\", label=\"" << DOT::EscapeString(TypeName);
+ Out << " [ shape=\"box\", label=\"" << llvm::DOT::EscapeString(TypeName);
// If the name of the class was a typedef or something different
// from the "real" class name, show the real class name in
@@ -139,9 +139,8 @@ void CXXRecordDecl::viewInheritance(ASTContext& Context) const {
int FD;
SmallString<128> Filename;
- std::error_code EC =
- sys::fs::createTemporaryFile(Self.getAsString(), "dot", FD, Filename);
- if (EC) {
+ if (std::error_code EC = llvm::sys::fs::createTemporaryFile(
+ Self.getAsString(), "dot", FD, Filename)) {
llvm::errs() << "Error: " << EC.message() << "\n";
return;
}
@@ -159,5 +158,3 @@ void CXXRecordDecl::viewInheritance(ASTContext& Context) const {
// Display the graph
DisplayGraph(Filename);
}
-
-}
diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp
index 378121c8e5b9..7503cbfc9805 100644
--- a/lib/AST/ItaniumCXXABI.cpp
+++ b/lib/AST/ItaniumCXXABI.cpp
@@ -106,7 +106,7 @@ public:
TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0);
uint64_t Width = Target.getTypeWidth(PtrDiff);
unsigned Align = Target.getTypeAlign(PtrDiff);
- if (MPT->getPointeeType()->isFunctionType())
+ if (MPT->isMemberFunctionPointer())
Width = 2 * Width;
return std::make_pair(Width, Align);
}
@@ -133,6 +133,22 @@ public:
return Layout.getNonVirtualSize() == PointerSize;
}
+ const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
+ return nullptr;
+ }
+
+ void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) override {}
+
+ void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE) override {}
+
+ Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx) override {
+ return nullptr;
+ }
+
MangleNumberingContext *createMangleNumberingContext() const override {
return new ItaniumNumberingContext();
}
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 156ad646fa6d..d07efaee7bba 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -42,8 +42,8 @@ using namespace clang;
namespace {
-/// \brief Retrieve the declaration context that should be used when mangling
-/// the given declaration.
+/// Retrieve the declaration context that should be used when mangling the given
+/// declaration.
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
// The ABI assumes that lambda closure types that occur within
// default arguments live in the context of the function. However, due to
@@ -69,6 +69,14 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) {
if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC))
return getEffectiveDeclContext(CD);
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ if (VD->isExternC())
+ return VD->getASTContext().getTranslationUnitDecl();
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isExternC())
+ return FD->getASTContext().getTranslationUnitDecl();
+
return DC;
}
@@ -156,12 +164,18 @@ public:
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) override;
+ void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
+ void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override;
void mangleItaniumThreadLocalWrapper(const VarDecl *D,
raw_ostream &) override;
void mangleStringLiteral(const StringLiteral *, raw_ostream &) override;
+ void mangleCXXVTableBitSet(const CXXRecordDecl *RD, raw_ostream &) override;
+
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
@@ -196,7 +210,7 @@ public:
/// @}
};
-/// CXXNameMangler - Manage the mangling of a single name.
+/// Manage the mangling of a single name.
class CXXNameMangler {
ItaniumMangleContextImpl &Context;
raw_ostream &Out;
@@ -207,7 +221,7 @@ class CXXNameMangler {
const NamedDecl *Structor;
unsigned StructorType;
- /// SeqID - The next subsitution sequence number.
+ /// The next substitution sequence number.
unsigned SeqID;
class FunctionTypeDepthState {
@@ -284,7 +298,7 @@ public:
#endif
raw_ostream &getStream() { return Out; }
- void mangle(const NamedDecl *D, StringRef Prefix = "_Z");
+ void mangle(const NamedDecl *D);
void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
void mangleNumber(const llvm::APSInt &I);
void mangleNumber(int64_t Number);
@@ -317,10 +331,8 @@ private:
void addSubstitution(uintptr_t Ptr);
void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
bool recursive = false);
void mangleUnresolvedName(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned KnownArity = UnknownArity);
@@ -350,6 +362,9 @@ private:
void manglePrefix(QualType type);
void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false);
void mangleTemplatePrefix(TemplateName Template);
+ bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType,
+ StringRef Prefix = "");
+ void mangleOperatorName(DeclarationName Name, unsigned Arity);
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
void mangleQualifiers(Qualifiers Quals);
void mangleRefQualifier(RefQualifierKind RefQualifier);
@@ -370,12 +385,14 @@ private:
void mangleAArch64NeonVectorType(const VectorType *T);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
+ void mangleMemberExprBase(const Expr *base, bool isArrow);
void mangleMemberExpr(const Expr *base, bool isArrow,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
+ void mangleInitListElements(const InitListExpr *InitList);
void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
@@ -439,11 +456,11 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
return true;
}
-void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
+void CXXNameMangler::mangle(const NamedDecl *D) {
// <mangled-name> ::= _Z <encoding>
// ::= <data name>
// ::= <special-name>
- Out << Prefix;
+ Out << "_Z";
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
mangleFunctionEncoding(FD);
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
@@ -519,7 +536,7 @@ static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
return DC;
}
-/// isStd - Return whether a given namespace is the 'std' namespace.
+/// Return whether a given namespace is the 'std' namespace.
static bool isStd(const NamespaceDecl *NS) {
if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
->isTranslationUnit())
@@ -748,8 +765,7 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
}
void CXXNameMangler::manglePrefix(QualType type) {
- if (const TemplateSpecializationType *TST =
- type->getAs<TemplateSpecializationType>()) {
+ if (const auto *TST = type->getAs<TemplateSpecializationType>()) {
if (!mangleSubstitution(QualType(TST, 0))) {
mangleTemplatePrefix(TST->getTemplateName());
@@ -759,17 +775,19 @@ void CXXNameMangler::manglePrefix(QualType type) {
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
- } else if (const DependentTemplateSpecializationType *DTST
- = type->getAs<DependentTemplateSpecializationType>()) {
- TemplateName Template
- = getASTContext().getDependentTemplateName(DTST->getQualifier(),
- DTST->getIdentifier());
- mangleTemplatePrefix(Template);
+ } else if (const auto *DTST =
+ type->getAs<DependentTemplateSpecializationType>()) {
+ if (!mangleSubstitution(QualType(DTST, 0))) {
+ TemplateName Template = getASTContext().getDependentTemplateName(
+ DTST->getQualifier(), DTST->getIdentifier());
+ mangleTemplatePrefix(Template);
- // FIXME: GCC does not appear to mangle the template arguments when
- // the template in question is a dependent template name. Should we
- // emulate that badness?
- mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ // FIXME: GCC does not appear to mangle the template arguments when
+ // the template in question is a dependent template name. Should we
+ // emulate that badness?
+ mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ addSubstitution(QualType(DTST, 0));
+ }
} else {
// We use the QualType mangle type variant here because it handles
// substitutions.
@@ -779,12 +797,9 @@ void CXXNameMangler::manglePrefix(QualType type) {
/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
///
-/// \param firstQualifierLookup - the entity found by unqualified lookup
-/// for the first name in the qualifier, if this is for a member expression
/// \param recursive - true if this is being called recursively,
/// i.e. if there is more prefix "to the right".
void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
bool recursive) {
// x, ::x
@@ -817,7 +832,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
case NestedNameSpecifier::Namespace:
if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
else
Out << "sr";
@@ -825,7 +840,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
break;
case NestedNameSpecifier::NamespaceAlias:
if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
else
Out << "sr";
@@ -842,193 +857,26 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
// - a template template parameter with arguments
// In all of these cases, we should have no prefix.
if (qualifier->getPrefix()) {
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
} else {
// Otherwise, all the cases want this.
Out << "sr";
}
- // Only certain other types are valid as prefixes; enumerate them.
- switch (type->getTypeClass()) {
- case Type::Builtin:
- case Type::Complex:
- case Type::Adjusted:
- case Type::Decayed:
- case Type::Pointer:
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionProto:
- case Type::FunctionNoProto:
- case Type::Enum:
- case Type::Paren:
- case Type::Elaborated:
- case Type::Attributed:
- case Type::Auto:
- case Type::PackExpansion:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::ObjCObjectPointer:
- case Type::Atomic:
- llvm_unreachable("type is illegal as a nested name specifier");
-
- case Type::SubstTemplateTypeParmPack:
- // FIXME: not clear how to mangle this!
- // template <class T...> class A {
- // template <class U...> void foo(decltype(T::foo(U())) x...);
- // };
- Out << "_SUBSTPACK_";
- break;
-
- // <unresolved-type> ::= <template-param>
- // ::= <decltype>
- // ::= <template-template-param> <template-args>
- // (this last is not official yet)
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::TemplateTypeParm:
- case Type::UnaryTransform:
- case Type::SubstTemplateTypeParm:
- unresolvedType:
- assert(!qualifier->getPrefix());
-
- // We only get here recursively if we're followed by identifiers.
- if (recursive) Out << 'N';
-
- // This seems to do everything we want. It's not really
- // sanctioned for a substituted template parameter, though.
- mangleType(QualType(type, 0));
-
- // We never want to print 'E' directly after an unresolved-type,
- // so we return directly.
+ if (mangleUnresolvedTypeOrSimpleId(QualType(type, 0), recursive ? "N" : ""))
return;
- case Type::Typedef:
- mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
- break;
-
- case Type::UnresolvedUsing:
- mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
- ->getIdentifier());
- break;
-
- case Type::Record:
- mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
- break;
-
- case Type::TemplateSpecialization: {
- const TemplateSpecializationType *tst
- = cast<TemplateSpecializationType>(type);
- TemplateName name = tst->getTemplateName();
- switch (name.getKind()) {
- case TemplateName::Template:
- case TemplateName::QualifiedTemplate: {
- TemplateDecl *temp = name.getAsTemplateDecl();
-
- // If the base is a template template parameter, this is an
- // unresolved type.
- assert(temp && "no template for template specialization type");
- if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
-
- mangleSourceName(temp->getIdentifier());
- break;
- }
-
- case TemplateName::OverloadedTemplate:
- case TemplateName::DependentTemplate:
- llvm_unreachable("invalid base for a template specialization type");
-
- case TemplateName::SubstTemplateTemplateParm: {
- SubstTemplateTemplateParmStorage *subst
- = name.getAsSubstTemplateTemplateParm();
- mangleExistingSubstitution(subst->getReplacement());
- break;
- }
-
- case TemplateName::SubstTemplateTemplateParmPack: {
- // FIXME: not clear how to mangle this!
- // template <template <class U> class T...> class A {
- // template <class U...> void foo(decltype(T<U>::foo) x...);
- // };
- Out << "_SUBSTPACK_";
- break;
- }
- }
-
- mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
- break;
- }
-
- case Type::InjectedClassName:
- mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
- ->getIdentifier());
- break;
-
- case Type::DependentName:
- mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
- break;
-
- case Type::DependentTemplateSpecialization: {
- const DependentTemplateSpecializationType *tst
- = cast<DependentTemplateSpecializationType>(type);
- mangleSourceName(tst->getIdentifier());
- mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
- break;
- }
- }
break;
}
case NestedNameSpecifier::Identifier:
// Member expressions can have these without prefixes.
- if (qualifier->getPrefix()) {
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ if (qualifier->getPrefix())
+ mangleUnresolvedPrefix(qualifier->getPrefix(),
/*recursive*/ true);
- } else if (firstQualifierLookup) {
-
- // Try to make a proper qualifier out of the lookup result, and
- // then just recurse on that.
- NestedNameSpecifier *newQualifier;
- if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {
- QualType type = getASTContext().getTypeDeclType(typeDecl);
-
- // Pretend we had a different nested name specifier.
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ nullptr,
- /*template*/ false,
- type.getTypePtr());
- } else if (NamespaceDecl *nspace =
- dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ nullptr,
- nspace);
- } else if (NamespaceAliasDecl *alias =
- dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ nullptr,
- alias);
- } else {
- // No sensible mangling to do here.
- newQualifier = nullptr;
- }
-
- if (newQualifier)
- return mangleUnresolvedPrefix(newQualifier, /*lookup*/ nullptr,
- recursive);
-
- } else {
+ else
Out << "sr";
- }
mangleSourceName(qualifier->getAsIdentifier());
break;
@@ -1043,16 +891,41 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
/// Mangle an unresolved-name, which is generally used for names which
/// weren't resolved to specific entities.
void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned knownArity) {
- if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
- mangleUnqualifiedName(nullptr, name, knownArity);
+ if (qualifier) mangleUnresolvedPrefix(qualifier);
+ switch (name.getNameKind()) {
+ // <base-unresolved-name> ::= <simple-id>
+ case DeclarationName::Identifier:
+ mangleSourceName(name.getAsIdentifierInfo());
+ break;
+ // <base-unresolved-name> ::= dn <destructor-name>
+ case DeclarationName::CXXDestructorName:
+ Out << "dn";
+ mangleUnresolvedTypeOrSimpleId(name.getCXXNameType());
+ break;
+ // <base-unresolved-name> ::= on <operator-name>
+ case DeclarationName::CXXConversionFunctionName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXOperatorName:
+ Out << "on";
+ mangleOperatorName(name, knownArity);
+ break;
+ case DeclarationName::CXXConstructorName:
+ llvm_unreachable("Can't mangle a constructor name!");
+ case DeclarationName::CXXUsingDirective:
+ llvm_unreachable("Can't mangle a using directive name!");
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCZeroArgSelector:
+ llvm_unreachable("Can't mangle Objective-C selector names here!");
+ }
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
DeclarationName Name,
unsigned KnownArity) {
+ unsigned Arity = KnownArity;
// <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name>
// ::= <source-name>
@@ -1163,7 +1036,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
Str += llvm::utostr(AnonStructId);
Out << Str.size();
- Out << Str.str();
+ Out << Str;
break;
}
@@ -1194,33 +1067,19 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
mangleCXXDtorType(Dtor_Complete);
break;
- case DeclarationName::CXXConversionFunctionName:
- // <operator-name> ::= cv <type> # (cast)
- Out << "cv";
- mangleType(Name.getCXXNameType());
- break;
-
- case DeclarationName::CXXOperatorName: {
- unsigned Arity;
- if (ND) {
+ case DeclarationName::CXXOperatorName:
+ if (ND && Arity == UnknownArity) {
Arity = cast<FunctionDecl>(ND)->getNumParams();
- // If we have a C++ member function, we need to include the 'this' pointer.
- // FIXME: This does not make sense for operators that are static, but their
- // names stay the same regardless of the arity (operator new for instance).
- if (isa<CXXMethodDecl>(ND))
- Arity++;
- } else
- Arity = KnownArity;
-
- mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
- break;
- }
-
+ // If we have a member function, we need to include the 'this' pointer.
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
+ if (!MD->isStatic())
+ Arity++;
+ }
+ // FALLTHROUGH
+ case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXLiteralOperatorName:
- // FIXME: This mangling is not yet official.
- Out << "li";
- mangleSourceName(Name.getCXXLiteralIdentifier());
+ mangleOperatorName(Name, Arity);
break;
case DeclarationName::CXXUsingDirective:
@@ -1529,7 +1388,8 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
assert(Dependent && "Unknown template name kind?");
- manglePrefix(Dependent->getQualifier());
+ if (NestedNameSpecifier *Qualifier = Dependent->getQualifier())
+ manglePrefix(Qualifier);
mangleUnscopedTemplateName(Template);
}
@@ -1591,7 +1451,7 @@ void CXXNameMangler::mangleType(TemplateName TN) {
// <class-enum-type> ::= <name>
// <name> ::= <nested-name>
- mangleUnresolvedPrefix(Dependent->getQualifier(), nullptr);
+ mangleUnresolvedPrefix(Dependent->getQualifier());
mangleSourceName(Dependent->getIdentifier());
break;
}
@@ -1620,6 +1480,181 @@ void CXXNameMangler::mangleType(TemplateName TN) {
addSubstitution(TN);
}
+bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
+ StringRef Prefix) {
+ // Only certain other types are valid as prefixes; enumerate them.
+ switch (Ty->getTypeClass()) {
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Adjusted:
+ case Type::Decayed:
+ case Type::Pointer:
+ case Type::BlockPointer:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::MemberPointer:
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ case Type::Paren:
+ case Type::Attributed:
+ case Type::Auto:
+ case Type::PackExpansion:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ case Type::Atomic:
+ llvm_unreachable("type is illegal as a nested name specifier");
+
+ case Type::SubstTemplateTypeParmPack:
+ // FIXME: not clear how to mangle this!
+ // template <class T...> class A {
+ // template <class U...> void foo(decltype(T::foo(U())) x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+
+ // <unresolved-type> ::= <template-param>
+ // ::= <decltype>
+ // ::= <template-template-param> <template-args>
+ // (this last is not official yet)
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::TemplateTypeParm:
+ case Type::UnaryTransform:
+ case Type::SubstTemplateTypeParm:
+ unresolvedType:
+ // Some callers want a prefix before the mangled type.
+ Out << Prefix;
+
+ // This seems to do everything we want. It's not really
+ // sanctioned for a substituted template parameter, though.
+ mangleType(Ty);
+
+ // We never want to print 'E' directly after an unresolved-type,
+ // so we return directly.
+ return true;
+
+ case Type::Typedef:
+ mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier());
+ break;
+
+ case Type::UnresolvedUsing:
+ mangleSourceName(
+ cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier());
+ break;
+
+ case Type::Enum:
+ case Type::Record:
+ mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier());
+ break;
+
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *TST =
+ cast<TemplateSpecializationType>(Ty);
+ TemplateName TN = TST->getTemplateName();
+ switch (TN.getKind()) {
+ case TemplateName::Template:
+ case TemplateName::QualifiedTemplate: {
+ TemplateDecl *TD = TN.getAsTemplateDecl();
+
+ // If the base is a template template parameter, this is an
+ // unresolved type.
+ assert(TD && "no template for template specialization type");
+ if (isa<TemplateTemplateParmDecl>(TD))
+ goto unresolvedType;
+
+ mangleSourceName(TD->getIdentifier());
+ break;
+ }
+
+ case TemplateName::OverloadedTemplate:
+ case TemplateName::DependentTemplate:
+ llvm_unreachable("invalid base for a template specialization type");
+
+ case TemplateName::SubstTemplateTemplateParm: {
+ SubstTemplateTemplateParmStorage *subst =
+ TN.getAsSubstTemplateTemplateParm();
+ mangleExistingSubstitution(subst->getReplacement());
+ break;
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ // FIXME: not clear how to mangle this!
+ // template <template <class U> class T...> class A {
+ // template <class U...> void foo(decltype(T<U>::foo) x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+ }
+ }
+
+ mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
+ break;
+ }
+
+ case Type::InjectedClassName:
+ mangleSourceName(
+ cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier());
+ break;
+
+ case Type::DependentName:
+ mangleSourceName(cast<DependentNameType>(Ty)->getIdentifier());
+ break;
+
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateSpecializationType *DTST =
+ cast<DependentTemplateSpecializationType>(Ty);
+ mangleSourceName(DTST->getIdentifier());
+ mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ break;
+ }
+
+ case Type::Elaborated:
+ return mangleUnresolvedTypeOrSimpleId(
+ cast<ElaboratedType>(Ty)->getNamedType(), Prefix);
+ }
+
+ return false;
+}
+
+void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXUsingDirective:
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCZeroArgSelector:
+ llvm_unreachable("Not an operator name");
+
+ case DeclarationName::CXXConversionFunctionName:
+ // <operator-name> ::= cv <type> # (cast)
+ Out << "cv";
+ mangleType(Name.getCXXNameType());
+ break;
+
+ case DeclarationName::CXXLiteralOperatorName:
+ Out << "li";
+ mangleSourceName(Name.getCXXLiteralIdentifier());
+ return;
+
+ case DeclarationName::CXXOperatorName:
+ mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
+ break;
+ }
+}
+
+
+
void
CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
switch (OO) {
@@ -2276,6 +2311,7 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) {
EltName = "Poly16";
break;
case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
EltName = "Poly64";
break;
default:
@@ -2519,6 +2555,29 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
}
+void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
+ // Ignore member expressions involving anonymous unions.
+ while (const auto *RT = Base->getType()->getAs<RecordType>()) {
+ if (!RT->getDecl()->isAnonymousStructOrUnion())
+ break;
+ const auto *ME = dyn_cast<MemberExpr>(Base);
+ if (!ME)
+ break;
+ Base = ME->getBase();
+ IsArrow = ME->isArrow();
+ }
+
+ if (Base->isImplicitCXXThis()) {
+ // Note: GCC mangles member expressions to the implicit 'this' as
+ // *this., whereas we represent them as this->. The Itanium C++ ABI
+ // does not specify anything here, so we follow GCC.
+ Out << "dtdefpT";
+ } else {
+ Out << (IsArrow ? "pt" : "dt");
+ mangleExpression(Base);
+ }
+}
+
/// Mangles a member expression.
void CXXNameMangler::mangleMemberExpr(const Expr *base,
bool isArrow,
@@ -2528,30 +2587,9 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
- if (base) {
-
- // Ignore member expressions involving anonymous unions.
- while (const auto *RT = base->getType()->getAs<RecordType>()) {
- if (!RT->getDecl()->isAnonymousStructOrUnion())
- break;
- const auto *ME = dyn_cast<MemberExpr>(base);
- if (!ME)
- break;
- base = ME->getBase();
- isArrow = ME->isArrow();
- }
-
- if (base->isImplicitCXXThis()) {
- // Note: GCC mangles member expressions to the implicit 'this' as
- // *this., whereas we represent them as this->. The Itanium C++ ABI
- // does not specify anything here, so we follow GCC.
- Out << "dtdefpT";
- } else {
- Out << (isArrow ? "pt" : "dt");
- mangleExpression(base);
- }
- }
- mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
+ if (base)
+ mangleMemberExprBase(base, isArrow);
+ mangleUnresolvedName(qualifier, member, arity);
}
/// Look at the callee of the given call expression and determine if
@@ -2592,6 +2630,13 @@ void CXXNameMangler::mangleCastExpression(const Expr *E, StringRef CastEncoding)
mangleExpression(ECE->getSubExpr());
}
+void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) {
+ if (auto *Syntactic = InitList->getSyntacticForm())
+ InitList = Syntactic;
+ for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
+ mangleExpression(InitList->getInit(i));
+}
+
void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
@@ -2631,7 +2676,6 @@ recurse:
// These all can only appear in local or variable-initialization
// contexts and so should never appear in a mangling.
case Expr::AddrLabelExprClass:
- case Expr::DesignatedInitExprClass:
case Expr::ImplicitValueInitExprClass:
case Expr::ParenListExprClass:
case Expr::LambdaExprClass:
@@ -2641,9 +2685,9 @@ recurse:
// FIXME: invent manglings for all these.
case Expr::BlockExprClass:
- case Expr::CXXPseudoDestructorExprClass:
case Expr::ChooseExprClass:
case Expr::CompoundLiteralExprClass:
+ case Expr::DesignatedInitExprClass:
case Expr::ExtVectorElementExprClass:
case Expr::GenericSelectionExprClass:
case Expr::ObjCEncodeExprClass:
@@ -2713,9 +2757,7 @@ recurse:
case Expr::InitListExprClass: {
Out << "il";
- const InitListExpr *InitList = cast<InitListExpr>(E);
- for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
- mangleExpression(InitList->getInit(i));
+ mangleInitListElements(cast<InitListExpr>(E));
Out << "E";
break;
}
@@ -2759,9 +2801,14 @@ recurse:
Out << "cl";
}
- mangleExpression(CE->getCallee(), CE->getNumArgs());
- for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
- mangleExpression(CE->getArg(I));
+ unsigned CallArity = CE->getNumArgs();
+ for (const Expr *Arg : CE->arguments())
+ if (isa<PackExpansionExpr>(Arg))
+ CallArity = UnknownArity;
+
+ mangleExpression(CE->getCallee(), CallArity);
+ for (const Expr *Arg : CE->arguments())
+ mangleExpression(Arg);
Out << 'E';
break;
}
@@ -2793,9 +2840,7 @@ recurse:
} else if (New->getInitializationStyle() == CXXNewExpr::ListInit &&
isa<InitListExpr>(Init)) {
// Only take InitListExprs apart for list-initialization.
- const InitListExpr *InitList = cast<InitListExpr>(Init);
- for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
- mangleExpression(InitList->getInit(i));
+ mangleInitListElements(cast<InitListExpr>(Init));
} else
mangleExpression(Init);
}
@@ -2803,6 +2848,33 @@ recurse:
break;
}
+ case Expr::CXXPseudoDestructorExprClass: {
+ const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
+ if (const Expr *Base = PDE->getBase())
+ mangleMemberExprBase(Base, PDE->isArrow());
+ NestedNameSpecifier *Qualifier = PDE->getQualifier();
+ QualType ScopeType;
+ if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
+ if (Qualifier) {
+ mangleUnresolvedPrefix(Qualifier,
+ /*Recursive=*/true);
+ mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType());
+ Out << 'E';
+ } else {
+ Out << "sr";
+ if (!mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()))
+ Out << 'E';
+ }
+ } else if (Qualifier) {
+ mangleUnresolvedPrefix(Qualifier);
+ }
+ // <base-unresolved-name> ::= dn <destructor-name>
+ Out << "dn";
+ QualType DestroyedType = PDE->getDestroyedType();
+ mangleUnresolvedTypeOrSimpleId(DestroyedType);
+ break;
+ }
+
case Expr::MemberExprClass: {
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
@@ -2813,9 +2885,9 @@ recurse:
case Expr::UnresolvedMemberExprClass: {
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
- mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), nullptr, ME->getMemberName(),
- Arity);
+ mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
+ ME->isArrow(), ME->getQualifier(), nullptr,
+ ME->getMemberName(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
break;
@@ -2824,8 +2896,9 @@ recurse:
case Expr::CXXDependentScopeMemberExprClass: {
const CXXDependentScopeMemberExpr *ME
= cast<CXXDependentScopeMemberExpr>(E);
- mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), ME->getFirstQualifierFoundInScope(),
+ mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
+ ME->isArrow(), ME->getQualifier(),
+ ME->getFirstQualifierFoundInScope(),
ME->getMember(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
@@ -2834,7 +2907,7 @@ recurse:
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
- mangleUnresolvedName(ULE->getQualifier(), nullptr, ULE->getName(), Arity);
+ mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
@@ -2856,26 +2929,55 @@ recurse:
break;
}
- case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXConstructExprClass: {
- const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);
+ const auto *CE = cast<CXXConstructExpr>(E);
+ if (!CE->isListInitialization() || CE->isStdInitListInitialization()) {
+ assert(
+ CE->getNumArgs() >= 1 &&
+ (CE->getNumArgs() == 1 || isa<CXXDefaultArgExpr>(CE->getArg(1))) &&
+ "implicit CXXConstructExpr must have one argument");
+ return mangleExpression(cast<CXXConstructExpr>(E)->getArg(0));
+ }
+ Out << "il";
+ for (auto *E : CE->arguments())
+ mangleExpression(E);
+ Out << "E";
+ break;
+ }
+
+ case Expr::CXXTemporaryObjectExprClass: {
+ const auto *CE = cast<CXXTemporaryObjectExpr>(E);
unsigned N = CE->getNumArgs();
+ bool List = CE->isListInitialization();
- if (CE->isListInitialization())
+ if (List)
Out << "tl";
else
Out << "cv";
mangleType(CE->getType());
- if (N != 1) Out << '_';
- for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
- if (N != 1) Out << 'E';
+ if (!List && N != 1)
+ Out << '_';
+ if (CE->isStdInitListInitialization()) {
+ // We implicitly created a std::initializer_list<T> for the first argument
+ // of a constructor of type U in an expression of the form U{a, b, c}.
+ // Strip all the semantic gunk off the initializer list.
+ auto *SILE =
+ cast<CXXStdInitializerListExpr>(CE->getArg(0)->IgnoreImplicit());
+ auto *ILE = cast<InitListExpr>(SILE->getSubExpr()->IgnoreImplicit());
+ mangleInitListElements(ILE);
+ } else {
+ for (auto *E : CE->arguments())
+ mangleExpression(E);
+ }
+ if (List || N != 1)
+ Out << 'E';
break;
}
case Expr::CXXScalarValueInitExprClass:
- Out <<"cv";
+ Out << "cv";
mangleType(E->getType());
- Out <<"_E";
+ Out << "_E";
break;
case Expr::CXXNoexceptExprClass:
@@ -3020,10 +3122,28 @@ recurse:
// Fall through to mangle the cast itself.
case Expr::CStyleCastExprClass:
- case Expr::CXXFunctionalCastExprClass:
mangleCastExpression(E, "cv");
break;
+ case Expr::CXXFunctionalCastExprClass: {
+ auto *Sub = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreImplicit();
+ // FIXME: Add isImplicit to CXXConstructExpr.
+ if (auto *CCE = dyn_cast<CXXConstructExpr>(Sub))
+ if (CCE->getParenOrBraceRange().isInvalid())
+ Sub = CCE->getArg(0)->IgnoreImplicit();
+ if (auto *StdInitList = dyn_cast<CXXStdInitializerListExpr>(Sub))
+ Sub = StdInitList->getSubExpr()->IgnoreImplicit();
+ if (auto *IL = dyn_cast<InitListExpr>(Sub)) {
+ Out << "tl";
+ mangleType(E->getType());
+ mangleInitListElements(IL);
+ Out << "E";
+ } else {
+ mangleCastExpression(E, "cv");
+ }
+ break;
+ }
+
case Expr::CXXStaticCastExprClass:
mangleCastExpression(E, "sc");
break;
@@ -3058,7 +3178,7 @@ recurse:
default:
// <expr-primary> ::= L <mangled-name> E # external name
Out << 'L';
- mangle(D, "_Z");
+ mangle(D);
Out << 'E';
break;
@@ -3101,8 +3221,7 @@ recurse:
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
- mangleUnresolvedName(DRE->getQualifier(), nullptr, DRE->getDeclName(),
- Arity);
+ mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
@@ -3327,6 +3446,9 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
case Ctor_Comdat:
Out << "C5";
break;
+ case Ctor_DefaultClosure:
+ case Ctor_CopyingClosure:
+ llvm_unreachable("closure constructors don't exist for the Itanium ABI!");
}
}
@@ -3410,8 +3532,8 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
const ValueDecl *D = DRE->getDecl();
if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {
- Out << "L";
- mangle(D, "_Z");
+ Out << 'L';
+ mangle(D);
Out << 'E';
break;
}
@@ -3440,13 +3562,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
Out << 'L';
// References to external entities use the mangled name; if the name would
// not normally be manged then mangle it as unqualified.
- //
- // FIXME: The ABI specifies that external names here should have _Z, but
- // gcc leaves this off.
- if (compensateMangling)
- mangle(D, "_Z");
- else
- mangle(D, "Z");
+ mangle(D);
Out << 'E';
if (compensateMangling)
@@ -3524,8 +3640,8 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
}
-/// \brief Determine whether the given type has any qualifiers that are
-/// relevant for substitutions.
+/// Determine whether the given type has any qualifiers that are relevant for
+/// substitutions.
static bool hasMangledSubstitutionQualifiers(QualType T) {
Qualifiers Qs = T.getQualifiers();
return Qs.getCVRQualifiers() || Qs.hasAddressSpace();
@@ -3571,8 +3687,8 @@ static bool isCharType(QualType T) {
T->isSpecificBuiltinType(BuiltinType::Char_U);
}
-/// isCharSpecialization - Returns whether a given type is a template
-/// specialization of a given name with a single argument of type char.
+/// Returns whether a given type is a template specialization of a given name
+/// with a single argument of type char.
static bool isCharSpecialization(QualType T, const char *Name) {
if (T.isNull())
return false;
@@ -3722,8 +3838,8 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
//
-/// \brief Mangles the name of the declaration D and emits that name to the
-/// given output stream.
+/// Mangles the name of the declaration D and emits that name to the given
+/// output stream.
///
/// If the declaration D requires a mangled name, this routine will emit that
/// mangled name to \p os and return true. Otherwise, \p os will be unchanged
@@ -3815,8 +3931,7 @@ void ItaniumMangleContextImpl::mangleCXXDtorThunk(
Mangler.mangleFunctionEncoding(DD);
}
-/// mangleGuardVariable - Returns the mangled name for a guard variable
-/// for the passed in VarDecl.
+/// Returns the mangled name for a guard variable for the passed in VarDecl.
void ItaniumMangleContextImpl::mangleStaticGuardVariable(const VarDecl *D,
raw_ostream &Out) {
// <special-name> ::= GV <object name> # Guard variable for one-time
@@ -3845,6 +3960,26 @@ void ItaniumMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
Mangler.getStream() << D->getName();
}
+void ItaniumMangleContextImpl::mangleSEHFilterExpression(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "__filt_";
+ if (shouldMangleDeclName(EnclosingDecl))
+ Mangler.mangle(EnclosingDecl);
+ else
+ Mangler.getStream() << EnclosingDecl->getName();
+}
+
+void ItaniumMangleContextImpl::mangleSEHFinallyBlock(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "__fin_";
+ if (shouldMangleDeclName(EnclosingDecl))
+ Mangler.mangle(EnclosingDecl);
+ else
+ Mangler.getStream() << EnclosingDecl->getName();
+}
+
void ItaniumMangleContextImpl::mangleItaniumThreadLocalInit(const VarDecl *D,
raw_ostream &Out) {
// <special-name> ::= TH <object name>
@@ -3923,6 +4058,22 @@ void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) {
mangleCXXRTTIName(Ty, Out);
}
+void ItaniumMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD,
+ raw_ostream &Out) {
+ Linkage L = RD->getLinkageInternal();
+ if (L == InternalLinkage || L == UniqueExternalLinkage) {
+ // This part of the identifier needs to be unique across all translation
+ // units in the linked program. The scheme fails if multiple translation
+ // units are compiled using the same relative source file path, or if
+ // multiple translation units are built from the same source file.
+ SourceManager &SM = getASTContext().getSourceManager();
+ Out << "[" << SM.getFileEntryForID(SM.getMainFileID())->getName() << "]";
+ }
+
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.mangleType(QualType(RD->getTypeForDecl(), 0));
+}
+
void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) {
llvm_unreachable("Can't mangle string literals");
}
diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp
index 0603d3b7b9b5..93ff77a2e964 100644
--- a/lib/AST/MicrosoftCXXABI.cpp
+++ b/lib/AST/MicrosoftCXXABI.cpp
@@ -31,11 +31,12 @@ class MicrosoftNumberingContext : public MangleNumberingContext {
llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
unsigned LambdaManglingNumber;
unsigned StaticLocalNumber;
+ unsigned StaticThreadlocalNumber;
public:
MicrosoftNumberingContext()
: MangleNumberingContext(), LambdaManglingNumber(0),
- StaticLocalNumber(0) {}
+ StaticLocalNumber(0), StaticThreadlocalNumber(0) {}
unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
return ++LambdaManglingNumber;
@@ -47,6 +48,8 @@ public:
}
unsigned getStaticLocalNumber(const VarDecl *VD) override {
+ if (VD->getTLSKind())
+ return ++StaticThreadlocalNumber;
return ++StaticLocalNumber;
}
@@ -63,6 +66,10 @@ public:
class MicrosoftCXXABI : public CXXABI {
ASTContext &Context;
+ llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
+ llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *>
+ CtorToDefaultArgExpr;
+
public:
MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
@@ -82,13 +89,36 @@ public:
return false;
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
+
// In the Microsoft ABI, classes can have one or two vtable pointers.
- CharUnits PointerSize =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+ CharUnits PointerSize =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
return Layout.getNonVirtualSize() == PointerSize ||
Layout.getNonVirtualSize() == PointerSize * 2;
- }
+ }
+
+ void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE) override {
+ CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE;
+ }
+
+ Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx) override {
+ return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)];
+ }
+
+ const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
+ return RecordToCopyCtor[RD];
+ }
+
+ void
+ addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) override {
+ assert(CD != nullptr);
+ assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
+ RecordToCopyCtor[RD] = CD;
+ }
MangleNumberingContext *createMangleNumberingContext() const override {
return new MicrosoftNumberingContext();
@@ -186,29 +216,28 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) {
std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
const MemberPointerType *MPT) const {
- const TargetInfo &Target = Context.getTargetInfo();
- assert(Target.getTriple().getArch() == llvm::Triple::x86 ||
- Target.getTriple().getArch() == llvm::Triple::x86_64);
- unsigned Ptrs, Ints;
- std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
// The nominal struct is laid out with pointers followed by ints and aligned
// to a pointer width if any are present and an int width otherwise.
+ const TargetInfo &Target = Context.getTargetInfo();
unsigned PtrSize = Target.getPointerWidth(0);
unsigned IntSize = Target.getIntWidth();
+
+ unsigned Ptrs, Ints;
+ std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
uint64_t Width = Ptrs * PtrSize + Ints * IntSize;
unsigned Align;
// When MSVC does x86_32 record layout, it aligns aggregate member pointers to
// 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for
// function memptrs.
- if (Ptrs + Ints > 1 && Target.getTriple().getArch() == llvm::Triple::x86)
- Align = 8 * 8;
+ if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit())
+ Align = 64;
else if (Ptrs)
Align = Target.getPointerAlign(0);
else
Align = Target.getIntAlign();
- if (Target.getTriple().getArch() == llvm::Triple::x86_64)
+ if (Target.getTriple().isArch64Bit())
Width = llvm::RoundUpToAlignment(Width, Align);
return std::make_pair(Width, Align);
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 72f90f67cbdf..77522c1f9c5d 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -67,11 +67,15 @@ static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
return getEffectiveDeclContext(cast<Decl>(DC));
}
-static const FunctionDecl *getStructor(const FunctionDecl *fn) {
- if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
- return ftd->getTemplatedDecl();
+static const FunctionDecl *getStructor(const NamedDecl *ND) {
+ if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+ return FTD->getTemplatedDecl();
- return fn;
+ const auto *FD = cast<FunctionDecl>(ND);
+ if (const auto *FTD = FD->getPrimaryTemplate())
+ return FTD->getTemplatedDecl();
+
+ return FD;
}
static bool isLambda(const NamedDecl *ND) {
@@ -89,6 +93,8 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier;
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
+ llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
+ llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
public:
MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
@@ -109,6 +115,16 @@ public:
void mangleCXXVBTable(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;
+ void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
+ uint32_t NumEntries, raw_ostream &Out) override;
+ void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
+ raw_ostream &Out) override;
+ void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
+ CXXCtorType CT, uint32_t Size, uint32_t NVOffset,
+ int32_t VBPtrOffset, uint32_t VBIndex,
+ raw_ostream &Out) override;
+ void mangleCXXCatchHandlerType(QualType T, uint32_t Flags,
+ raw_ostream &Out) override;
void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
@@ -131,10 +147,18 @@ public:
void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
raw_ostream &) override;
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
+ void mangleThreadSafeStaticGuardVariable(const VarDecl *D, unsigned GuardNum,
+ raw_ostream &Out) override;
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) override;
+ void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
+ void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
+ void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
+ raw_ostream &Out) override;
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
@@ -211,6 +235,12 @@ public:
64) {}
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
+ const CXXConstructorDecl *D, CXXCtorType Type)
+ : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
+ PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+ 64) {}
+
+ MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
const CXXDestructorDecl *D, CXXDtorType Type)
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
@@ -220,7 +250,7 @@ public:
void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
void mangleName(const NamedDecl *ND);
- void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleFunctionEncoding(const FunctionDecl *FD, bool ShouldMangle);
void mangleVariableEncoding(const VarDecl *VD);
void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD);
void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
@@ -247,7 +277,7 @@ private:
void mangleQualifiers(Qualifiers Quals, bool IsMember);
void mangleRefQualifier(RefQualifierKind RefQualifier);
void manglePointerCVQualifiers(Qualifiers Quals);
- void manglePointerExtQualifiers(Qualifiers Quals, const Type *PointeeType);
+ void manglePointerExtQualifiers(Qualifiers Quals, QualType PointeeType);
void mangleUnscopedTemplateName(const TemplateDecl *ND);
void
@@ -261,6 +291,7 @@ private:
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \
+ Qualifiers Quals, \
SourceRange Range);
#include "clang/AST/TypeNodes.def"
#undef ABSTRACT_TYPE
@@ -271,6 +302,7 @@ private:
void mangleDecayedArrayType(const ArrayType *T);
void mangleArrayType(const ArrayType *T);
void mangleFunctionClass(const FunctionDecl *FD);
+ void mangleCallingConvention(CallingConv CC);
void mangleCallingConvention(const FunctionType *T);
void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
void mangleExpression(const Expr *E);
@@ -352,7 +384,7 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
Out << Prefix;
mangleName(D);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- mangleFunctionEncoding(FD);
+ mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD));
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleVariableEncoding(VD);
else {
@@ -365,7 +397,8 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
}
}
-void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD,
+ bool ShouldMangle) {
// <type-encoding> ::= <function-class> <function-type>
// Since MSVC operates on the type as written and not the canonical type, it
@@ -380,13 +413,20 @@ void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
// extern "C" functions can hold entities that must be mangled.
// As it stands, these functions still need to get expressed in the full
// external name. They have their class and type omitted, replaced with '9'.
- if (Context.shouldMangleDeclName(FD)) {
- // First, the function class.
+ if (ShouldMangle) {
+ // We would like to mangle all extern "C" functions using this additional
+ // component but this would break compatibility with MSVC's behavior.
+ // Instead, do this when we know that compatibility isn't important (in
+ // other words, when it is an overloaded extern "C" funciton).
+ if (FD->isExternC() && FD->hasAttr<OverloadableAttr>())
+ Out << "$$J0";
+
mangleFunctionClass(FD);
mangleFunctionType(FT, FD);
- } else
+ } else {
Out << '9';
+ }
}
void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
@@ -422,7 +462,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
Ty->isMemberPointerType()) {
mangleType(Ty, SR, QMM_Drop);
manglePointerExtQualifiers(
- Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), nullptr);
+ Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), QualType());
if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) {
mangleQualifiers(MPT->getPointeeType().getQualifiers(), true);
// Member pointers are suffixed with a back reference to the member
@@ -525,7 +565,7 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
}
} else {
mangleName(MD);
- mangleFunctionEncoding(MD);
+ mangleFunctionEncoding(MD, /*ShouldMangle=*/true);
}
} else {
// Null single inheritance member functions are encoded as a simple nullptr.
@@ -559,7 +599,7 @@ void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
Out << "$B";
mangleNumber(OffsetInVFTable);
Out << 'A';
- Out << (PointersAre64Bit ? 'A' : 'E');
+ mangleCallingConvention(MD->getType()->getAs<FunctionProtoType>());
}
void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
@@ -757,12 +797,18 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
llvm_unreachable("Can't mangle Objective-C selector names here!");
case DeclarationName::CXXConstructorName:
- if (ND == Structor) {
- assert(StructorType == Ctor_Complete &&
- "Should never be asked to mangle a ctor other than complete");
+ if (Structor == getStructor(ND)) {
+ if (StructorType == Ctor_CopyingClosure) {
+ Out << "?_O";
+ return;
+ }
+ if (StructorType == Ctor_DefaultClosure) {
+ Out << "?_F";
+ return;
+ }
}
Out << "?0";
- break;
+ return;
case DeclarationName::CXXDestructorName:
if (ND == Structor)
@@ -1134,10 +1180,13 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
cast<ValueDecl>(ND));
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
- if (MD && MD->isInstance())
+ if (MD && MD->isInstance()) {
mangleMemberFunctionPointer(MD->getParent()->getMostRecentDecl(), MD);
- else
- mangle(FD, "$1?");
+ } else {
+ Out << "$1?";
+ mangleName(FD);
+ mangleFunctionEncoding(FD, /*ShouldMangle=*/true);
+ }
} else {
mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?");
}
@@ -1171,7 +1220,12 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
if (TemplateArgs.empty()) {
if (isa<TemplateTypeParmDecl>(Parm) ||
isa<TemplateTemplateParmDecl>(Parm))
- Out << "$$V";
+ // MSVC 2015 changed the mangling for empty expanded template packs,
+ // use the old mangling for link compatibility for old versions.
+ Out << (Context.getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2015)
+ ? "$$V"
+ : "$$$V");
else if (isa<NonTypeTemplateParmDecl>(Parm))
Out << "$S";
else
@@ -1298,11 +1352,11 @@ MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
}
}
-void
-MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
- const Type *PointeeType) {
+void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
+ QualType PointeeType) {
bool HasRestrict = Quals.hasRestrict();
- if (PointersAre64Bit && (!PointeeType || !PointeeType->isFunctionType()))
+ if (PointersAre64Bit &&
+ (PointeeType.isNull() || !PointeeType->isFunctionType()))
Out << 'E';
if (HasRestrict)
@@ -1338,29 +1392,38 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
// e.g.
// void (*x)(void) will not form a backreference with void x(void)
void *TypePtr;
- if (const DecayedType *DT = T->getAs<DecayedType>()) {
- TypePtr = DT->getOriginalType().getCanonicalType().getAsOpaquePtr();
+ if (const auto *DT = T->getAs<DecayedType>()) {
+ QualType OriginalType = DT->getOriginalType();
+ // All decayed ArrayTypes should be treated identically; as-if they were
+ // a decayed IncompleteArrayType.
+ if (const auto *AT = getASTContext().getAsArrayType(OriginalType))
+ OriginalType = getASTContext().getIncompleteArrayType(
+ AT->getElementType(), AT->getSizeModifier(),
+ AT->getIndexTypeCVRQualifiers());
+
+ TypePtr = OriginalType.getCanonicalType().getAsOpaquePtr();
// If the original parameter was textually written as an array,
// instead treat the decayed parameter like it's const.
//
// e.g.
// int [] -> int * const
- if (DT->getOriginalType()->isArrayType())
+ if (OriginalType->isArrayType())
T = T.withConst();
- } else
+ } else {
TypePtr = T.getCanonicalType().getAsOpaquePtr();
+ }
ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
if (Found == TypeBackReferences.end()) {
- size_t OutSizeBefore = Out.GetNumBytesInBuffer();
+ size_t OutSizeBefore = Out.tell();
mangleType(T, Range, QMM_Drop);
// See if it's worth creating a back reference.
// Only types longer than 1 character are considered
// and only 10 back references slots are available:
- bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1);
+ bool LongerThanOneChar = (Out.tell() - OutSizeBefore > 1);
if (LongerThanOneChar && TypeBackReferences.size() < 10) {
size_t Size = TypeBackReferences.size();
TypeBackReferences[TypePtr] = Size;
@@ -1388,7 +1451,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
}
bool IsPointer = T->isAnyPointerType() || T->isMemberPointerType() ||
- T->isBlockPointerType();
+ T->isReferenceType() || T->isBlockPointerType();
switch (QMM) {
case QMM_Drop:
@@ -1415,11 +1478,6 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
break;
}
- // We have to mangle these now, while we still have enough information.
- if (IsPointer) {
- manglePointerCVQualifiers(Quals);
- manglePointerExtQualifiers(Quals, T->getPointeeType().getTypePtr());
- }
const Type *ty = T.getTypePtr();
switch (ty->getTypeClass()) {
@@ -1430,7 +1488,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
return;
#define TYPE(CLASS, PARENT) \
case Type::CLASS: \
- mangleType(cast<CLASS##Type>(ty), Range); \
+ mangleType(cast<CLASS##Type>(ty), Quals, Range); \
break;
#include "clang/AST/TypeNodes.def"
#undef ABSTRACT_TYPE
@@ -1439,7 +1497,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
}
}
-void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
+void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
SourceRange Range) {
// <type> ::= <builtin-type>
// <builtin-type> ::= X # void
@@ -1525,7 +1583,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
}
// <type> ::= <function-type>
-void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
+void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, Qualifiers,
SourceRange) {
// Structors only appear in decls, so at this point we know it's not a
// structor type.
@@ -1539,7 +1597,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
}
}
void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
- SourceRange) {
+ Qualifiers, SourceRange) {
llvm_unreachable("Can't mangle K&R function prototypes");
}
@@ -1553,24 +1611,34 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
SourceRange Range;
if (D) Range = D->getSourceRange();
- bool IsStructor = false, HasThisQuals = ForceThisQuals;
+ bool IsStructor = false, HasThisQuals = ForceThisQuals, IsCtorClosure = false;
+ CallingConv CC = T->getCallConv();
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) {
if (MD->isInstance())
HasThisQuals = true;
- if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
+ if (isa<CXXDestructorDecl>(MD)) {
+ IsStructor = true;
+ } else if (isa<CXXConstructorDecl>(MD)) {
IsStructor = true;
+ IsCtorClosure = (StructorType == Ctor_CopyingClosure ||
+ StructorType == Ctor_DefaultClosure) &&
+ getStructor(MD) == Structor;
+ if (IsCtorClosure)
+ CC = getASTContext().getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true);
+ }
}
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
if (HasThisQuals) {
Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals());
- manglePointerExtQualifiers(Quals, /*PointeeType=*/nullptr);
+ manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType());
mangleRefQualifier(Proto->getRefQualifier());
mangleQualifiers(Quals, /*IsMember=*/false);
}
- mangleCallingConvention(T);
+ mangleCallingConvention(CC);
// <return-type> ::= <type>
// ::= @ # structors (they have no declared return type)
@@ -1584,6 +1652,29 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z");
return;
}
+ if (IsCtorClosure) {
+ // Default constructor closure and copy constructor closure both return
+ // void.
+ Out << 'X';
+
+ if (StructorType == Ctor_DefaultClosure) {
+ // Default constructor closure always has no arguments.
+ Out << 'X';
+ } else if (StructorType == Ctor_CopyingClosure) {
+ // Copy constructor closure always takes an unqualified reference.
+ mangleArgumentType(getASTContext().getLValueReferenceType(
+ Proto->getParamType(0)
+ ->getAs<LValueReferenceType>()
+ ->getPointeeType(),
+ /*SpelledAsLValue=*/true),
+ Range);
+ Out << '@';
+ } else {
+ llvm_unreachable("unexpected constructor closure!");
+ }
+ Out << 'Z';
+ return;
+ }
Out << '@';
} else {
QualType ResultType = Proto->getReturnType();
@@ -1608,7 +1699,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
Out << 'X';
} else {
// Happens for function pointer type arguments for example.
- for (const QualType Arg : Proto->param_types())
+ for (const QualType &Arg : Proto->param_types())
mangleArgumentType(Arg, Range);
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
@@ -1673,10 +1764,11 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
else
Out << 'Q';
}
- } else
+ } else {
Out << 'Y';
+ }
}
-void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
+void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
// <calling-convention> ::= A # __cdecl
// ::= B # __export __cdecl
// ::= C # __pascal
@@ -1693,7 +1785,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
// that keyword. (It didn't actually export them, it just made them so
// that they could be in a DLL and somebody from another module could call
// them.)
- CallingConv CC = T->getCallConv();
+
switch (CC) {
default:
llvm_unreachable("Unsupported CC for mangling");
@@ -1707,6 +1799,9 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
case CC_X86VectorCall: Out << 'Q'; break;
}
}
+void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
+ mangleCallingConvention(T->getCallConv());
+}
void MicrosoftCXXNameMangler::mangleThrowSpecification(
const FunctionProtoType *FT) {
// <throw-spec> ::= Z # throw(...) (default)
@@ -1719,7 +1814,7 @@ void MicrosoftCXXNameMangler::mangleThrowSpecification(
}
void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
// Probably should be mangled as a template instantiation; need to see what
// VC does first.
DiagnosticsEngine &Diags = Context.getDiags();
@@ -1734,10 +1829,12 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
// <struct-type> ::= U <name>
// <class-type> ::= V <name>
// <enum-type> ::= W4 <name>
-void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {
+void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers,
+ SourceRange) {
mangleType(cast<TagType>(T)->getDecl());
}
-void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
+void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers,
+ SourceRange) {
mangleType(cast<TagType>(T)->getDecl());
}
void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
@@ -1772,39 +1869,41 @@ void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) {
manglePointerCVQualifiers(T->getElementType().getQualifiers());
mangleType(T->getElementType(), SourceRange());
}
-void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
+void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, Qualifiers,
SourceRange) {
llvm_unreachable("Should have been special cased");
}
-void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T,
+void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T, Qualifiers,
SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,
- SourceRange) {
+ Qualifiers, SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
- SourceRange) {
+ Qualifiers, SourceRange) {
llvm_unreachable("Should have been special cased");
}
void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
QualType ElementTy(T, 0);
SmallVector<llvm::APInt, 3> Dimensions;
for (;;) {
- if (const ConstantArrayType *CAT =
- getASTContext().getAsConstantArrayType(ElementTy)) {
+ if (ElementTy->isConstantArrayType()) {
+ const ConstantArrayType *CAT =
+ getASTContext().getAsConstantArrayType(ElementTy);
Dimensions.push_back(CAT->getSize());
ElementTy = CAT->getElementType();
+ } else if (ElementTy->isIncompleteArrayType()) {
+ const IncompleteArrayType *IAT =
+ getASTContext().getAsIncompleteArrayType(ElementTy);
+ Dimensions.push_back(llvm::APInt(32, 0));
+ ElementTy = IAT->getElementType();
} else if (ElementTy->isVariableArrayType()) {
const VariableArrayType *VAT =
getASTContext().getAsVariableArrayType(ElementTy);
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this variable-length array yet");
- Diags.Report(VAT->getSizeExpr()->getExprLoc(), DiagID)
- << VAT->getBracketsRange();
- return;
+ Dimensions.push_back(llvm::APInt(32, 0));
+ ElementTy = VAT->getElementType();
} else if (ElementTy->isDependentSizedArrayType()) {
// The dependent expression has to be folded into a constant (TODO).
const DependentSizedArrayType *DSAT =
@@ -1815,12 +1914,9 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID)
<< DSAT->getBracketsRange();
return;
- } else if (const IncompleteArrayType *IAT =
- getASTContext().getAsIncompleteArrayType(ElementTy)) {
- Dimensions.push_back(llvm::APInt(32, 0));
- ElementTy = IAT->getElementType();
+ } else {
+ break;
}
- else break;
}
Out << 'Y';
// <dimension-count> ::= <number> # number of extra dimensions
@@ -1833,9 +1929,11 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
// <type> ::= <pointer-to-member-type>
// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
// <class name> <type>
-void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
+void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, Qualifiers Quals,
SourceRange Range) {
QualType PointeeType = T->getPointeeType();
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, PointeeType);
if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
Out << '8';
mangleName(T->getClass()->castAs<RecordType>()->getDecl());
@@ -1848,7 +1946,7 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
}
void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this template type parameter type yet");
@@ -1856,9 +1954,8 @@ void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(
- const SubstTemplateTypeParmPackType *T,
- SourceRange Range) {
+void MicrosoftCXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T,
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this substituted parameter pack yet");
@@ -1869,40 +1966,46 @@ void MicrosoftCXXNameMangler::mangleType(
// <type> ::= <pointer-type>
// <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
// # the E is required for 64-bit non-static pointers
-void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
+void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
SourceRange Range) {
- QualType PointeeTy = T->getPointeeType();
- mangleType(PointeeTy, Range);
+ QualType PointeeType = T->getPointeeType();
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, PointeeType);
+ mangleType(PointeeType, Range);
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
- SourceRange Range) {
+ Qualifiers Quals, SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, PointeeType);
// Object pointers never have qualifiers.
Out << 'A';
- manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
- mangleType(T->getPointeeType(), Range);
+ mangleType(PointeeType, Range);
}
// <type> ::= <reference-type>
// <reference-type> ::= A E? <cvr-qualifiers> <type>
// # the E is required for 64-bit non-static lvalue references
void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
- SourceRange Range) {
- Out << 'A';
- manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
- mangleType(T->getPointeeType(), Range);
+ Qualifiers Quals, SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ Out << (Quals.hasVolatile() ? 'B' : 'A');
+ manglePointerExtQualifiers(Quals, PointeeType);
+ mangleType(PointeeType, Range);
}
// <type> ::= <r-value-reference-type>
// <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type>
// # the E is required for 64-bit non-static rvalue references
void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
- SourceRange Range) {
- Out << "$$Q";
- manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr());
- mangleType(T->getPointeeType(), Range);
+ Qualifiers Quals, SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ Out << (Quals.hasVolatile() ? "$$R" : "$$Q");
+ manglePointerExtQualifiers(Quals, PointeeType);
+ mangleType(PointeeType, Range);
}
-void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,
+void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -1911,7 +2014,7 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const VectorType *T,
+void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
SourceRange Range) {
const BuiltinType *ET = T->getElementType()->getAs<BuiltinType>();
assert(ET && "vectors with non-builtin elements are unsupported");
@@ -1939,13 +2042,13 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T,
// our own mangling to handle uses of __vector_size__ on user-specified
// types, and for extensions like __v4sf.
Out << "T__clang_vec" << T->getNumElements() << '_';
- mangleType(ET, Range);
+ mangleType(ET, Quals, Range);
}
Out << "@@";
}
-void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
+void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -1954,7 +2057,7 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
<< Range;
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this dependent-sized extended vector type yet");
@@ -1962,14 +2065,14 @@ void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T,
+void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
SourceRange) {
// ObjC interfaces have structs underlying them.
Out << 'U';
mangleName(T->getDecl());
}
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
+void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
SourceRange Range) {
// We don't allow overloading by different protocol qualification,
// so mangling them isn't necessary.
@@ -1977,20 +2080,23 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
}
void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
- SourceRange Range) {
+ Qualifiers Quals, SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ manglePointerCVQualifiers(Quals);
+ manglePointerExtQualifiers(Quals, PointeeType);
+
Out << "_E";
- QualType pointee = T->getPointeeType();
- mangleFunctionType(pointee->castAs<FunctionProtoType>());
+ mangleFunctionType(PointeeType->castAs<FunctionProtoType>());
}
void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *,
- SourceRange) {
+ Qualifiers, SourceRange) {
llvm_unreachable("Cannot mangle injected class name type.");
}
void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this template specialization type yet");
@@ -1998,7 +2104,7 @@ void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T,
+void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2008,8 +2114,8 @@ void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T,
}
void MicrosoftCXXNameMangler::mangleType(
- const DependentTemplateSpecializationType *T,
- SourceRange Range) {
+ const DependentTemplateSpecializationType *T, Qualifiers,
+ SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this dependent template specialization type yet");
@@ -2017,7 +2123,7 @@ void MicrosoftCXXNameMangler::mangleType(
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T,
+void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2026,7 +2132,7 @@ void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T,
+void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2035,7 +2141,7 @@ void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T,
+void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2044,7 +2150,7 @@ void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T,
+void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2054,7 +2160,7 @@ void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T,
}
void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
- SourceRange Range) {
+ Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this unary transform type yet");
@@ -2062,7 +2168,8 @@ void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) {
+void MicrosoftCXXNameMangler::mangleType(const AutoType *T, Qualifiers,
+ SourceRange Range) {
assert(T->getDeducedType().isNull() && "expecting a dependent type!");
DiagnosticsEngine &Diags = Context.getDiags();
@@ -2072,7 +2179,7 @@ void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) {
<< Range;
}
-void MicrosoftCXXNameMangler::mangleType(const AtomicType *T,
+void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -2273,6 +2380,74 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T,
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
}
+void MicrosoftMangleContextImpl::mangleCXXCatchHandlerType(QualType T,
+ uint32_t Flags,
+ raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "llvm.eh.handlertype.";
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+ Mangler.getStream() << '.' << Flags;
+}
+
+void MicrosoftMangleContextImpl::mangleCXXThrowInfo(QualType T,
+ bool IsConst,
+ bool IsVolatile,
+ uint32_t NumEntries,
+ raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_TI";
+ if (IsConst)
+ Mangler.getStream() << 'C';
+ if (IsVolatile)
+ Mangler.getStream() << 'V';
+ Mangler.getStream() << NumEntries;
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+}
+
+void MicrosoftMangleContextImpl::mangleCXXCatchableTypeArray(
+ QualType T, uint32_t NumEntries, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_CTA";
+ Mangler.getStream() << NumEntries;
+ Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
+}
+
+void MicrosoftMangleContextImpl::mangleCXXCatchableType(
+ QualType T, const CXXConstructorDecl *CD, CXXCtorType CT, uint32_t Size,
+ uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBIndex,
+ raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_CT";
+
+ llvm::SmallString<64> RTTIMangling;
+ {
+ llvm::raw_svector_ostream Stream(RTTIMangling);
+ mangleCXXRTTI(T, Stream);
+ }
+ Mangler.getStream() << RTTIMangling.substr(1);
+
+ // VS2015 CTP6 omits the copy-constructor in the mangled name. This name is,
+ // in fact, superfluous but I'm not sure the change was made consciously.
+ // TODO: Revisit this when VS2015 gets released.
+ llvm::SmallString<64> CopyCtorMangling;
+ if (CD) {
+ llvm::raw_svector_ostream Stream(CopyCtorMangling);
+ mangleCXXCtor(CD, CT, Stream);
+ }
+ Mangler.getStream() << CopyCtorMangling.substr(1);
+
+ Mangler.getStream() << Size;
+ if (VBPtrOffset == -1) {
+ if (NVOffset) {
+ Mangler.getStream() << NVOffset;
+ }
+ } else {
+ Mangler.getStream() << NVOffset;
+ Mangler.getStream() << VBPtrOffset;
+ Mangler.getStream() << VBIndex;
+ }
+}
+
void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor(
const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
@@ -2318,6 +2493,28 @@ void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(
Mangler.getStream() << '@';
}
+void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ // The function body is in the same comdat as the function with the handler,
+ // so the numbering here doesn't have to be the same across TUs.
+ //
+ // <mangled-name> ::= ?filt$ <filter-number> @0
+ Mangler.getStream() << "\01?filt$" << SEHFilterIds[EnclosingDecl]++ << "@0@";
+ Mangler.mangleName(EnclosingDecl);
+}
+
+void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ // The function body is in the same comdat as the function with the handler,
+ // so the numbering here doesn't have to be the same across TUs.
+ //
+ // <mangled-name> ::= ?fin$ <filter-number> @0
+ Mangler.getStream() << "\01?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
+ Mangler.mangleName(EnclosingDecl);
+}
+
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
// This is just a made up unique string for the purposes of tbaa. undname
// does *not* know how to demangle it.
@@ -2329,7 +2526,7 @@ void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
CXXCtorType Type,
raw_ostream &Out) {
- MicrosoftCXXNameMangler mangler(*this, Out);
+ MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
mangler.mangle(D);
}
@@ -2348,18 +2545,18 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
getDiags().Report(VD->getLocation(), DiagID);
}
+void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
+ const VarDecl *VD, unsigned GuardNum, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+
+ Mangler.getStream() << "\01?$TSS" << GuardNum << '@';
+ Mangler.mangleNestedName(VD);
+}
+
void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
raw_ostream &Out) {
- // TODO: This is not correct, especially with respect to VS "14". VS "14"
- // utilizes thread local variables to implement thread safe, re-entrant
- // initialization for statics. They no longer differentiate between an
- // externally visible and non-externally visible static with respect to
- // mangling, they all get $TSS <number>.
- //
- // N.B. This means that they can get more than 32 static variable guards in a
- // scope. It also means that they broke compatibility with their own ABI.
-
// <guard-name> ::= ?_B <postfix> @5 <scope-depth>
+ // ::= ?__J <postfix> @5 <scope-depth>
// ::= ?$S <guard-num> @ <postfix> @4IA
// The first mangling is what MSVC uses to guard static locals in inline
@@ -2371,8 +2568,11 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
MicrosoftCXXNameMangler Mangler(*this, Out);
bool Visible = VD->isExternallyVisible();
- // <operator-name> ::= ?_B # local static guard
- Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@");
+ if (Visible) {
+ Mangler.getStream() << (VD->getTLSKind() ? "\01??__J" : "\01??_B");
+ } else {
+ Mangler.getStream() << "\01?$S1@";
+ }
unsigned ScopeDepth = 0;
if (Visible && !getNextDiscriminator(VD, ScopeDepth))
// If we do not have a discriminator and are emitting a guard variable for
@@ -2553,6 +2753,11 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
Mangler.getStream() << '@';
}
+void MicrosoftMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD,
+ raw_ostream &Out) {
+ llvm::report_fatal_error("Cannot mangle bitsets yet");
+}
+
MicrosoftMangleContext *
MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
return new MicrosoftMangleContextImpl(Context, Diags);
diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp
index 3dc750a81787..2749100e14a2 100644
--- a/lib/AST/NSAPI.cpp
+++ b/lib/AST/NSAPI.cpp
@@ -27,7 +27,10 @@ IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
"NSMutableArray",
"NSDictionary",
"NSMutableDictionary",
- "NSNumber"
+ "NSNumber",
+ "NSMutableSet",
+ "NSCountedSet",
+ "NSMutableOrderedSet"
};
if (!ClassIds[K])
@@ -124,6 +127,25 @@ Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
+ case NSMutableArr_addObject:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
+ break;
+ case NSMutableArr_insertObjectAtIndex: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("insertObject"),
+ &Ctx.Idents.get("atIndex")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSMutableArr_setObjectAtIndexedSubscript: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("atIndexedSubscript")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
}
return (NSArraySelectors[MK] = Sel);
}
@@ -209,6 +231,22 @@ Selector NSAPI::getNSDictionarySelector(
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
+ case NSMutableDict_setObjectForKeyedSubscript: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("forKeyedSubscript")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSMutableDict_setValueForKey: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setValue"),
+ &Ctx.Idents.get("forKey")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
}
return (NSDictionarySelectors[MK] = Sel);
}
@@ -227,6 +265,63 @@ NSAPI::getNSDictionaryMethodKind(Selector Sel) {
return None;
}
+Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
+ if (NSSetSelectors[MK].isNull()) {
+ Selector Sel;
+ switch (MK) {
+ case NSMutableSet_addObject:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
+ break;
+ case NSOrderedSet_insertObjectAtIndex: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("insertObject"),
+ &Ctx.Idents.get("atIndex")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSOrderedSet_setObjectAtIndex: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("atIndex")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSOrderedSet_setObjectAtIndexedSubscript: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("atIndexedSubscript")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSOrderedSet_replaceObjectAtIndexWithObject: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("replaceObjectAtIndex"),
+ &Ctx.Idents.get("withObject")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ }
+ return (NSSetSelectors[MK] = Sel);
+ }
+
+ return NSSetSelectors[MK];
+}
+
+Optional<NSAPI::NSSetMethodKind>
+NSAPI::getNSSetMethodKind(Selector Sel) {
+ for (unsigned i = 0; i != NumNSSetMethods; ++i) {
+ NSSetMethodKind MK = NSSetMethodKind(i);
+ if (Sel == getNSSetSelector(MK))
+ return MK;
+ }
+
+ return None;
+}
+
Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
bool Instance) const {
static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
@@ -410,6 +505,11 @@ StringRef NSAPI::GetNSIntegralKind(QualType T) const {
return StringRef();
}
+bool NSAPI::isMacroDefined(StringRef Id) const {
+ // FIXME: Check whether the relevant module macros are visible.
+ return Ctx.Idents.get(Id).hasMacroDefinition();
+}
+
bool NSAPI::isObjCTypedef(QualType T,
StringRef name, IdentifierInfo *&II) const {
if (!Ctx.getLangOpts().ObjC1)
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 0d070a4bfbfc..2101a5534a6b 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -55,6 +55,52 @@ struct BaseSubobjectInfo {
const BaseSubobjectInfo *Derived;
};
+/// \brief Externally provided layout. Typically used when the AST source, such
+/// as DWARF, lacks all the information that was available at compile time, such
+/// as alignment attributes on fields and pragmas in effect.
+struct ExternalLayout {
+ ExternalLayout() : Size(0), Align(0) {}
+
+ /// \brief Overall record size in bits.
+ uint64_t Size;
+
+ /// \brief Overall record alignment in bits.
+ uint64_t Align;
+
+ /// \brief Record field offsets in bits.
+ llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
+
+ /// \brief Direct, non-virtual base offsets.
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
+
+ /// \brief Virtual base offsets.
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
+
+ /// Get the offset of the given field. The external source must provide
+ /// entries for all fields in the record.
+ uint64_t getExternalFieldOffset(const FieldDecl *FD) {
+ assert(FieldOffsets.count(FD) &&
+ "Field does not have an external offset");
+ return FieldOffsets[FD];
+ }
+
+ bool getExternalNVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {
+ auto Known = BaseOffsets.find(RD);
+ if (Known == BaseOffsets.end())
+ return false;
+ BaseOffset = Known->second;
+ return true;
+ }
+
+ bool getExternalVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {
+ auto Known = VirtualBaseOffsets.find(RD);
+ if (Known == VirtualBaseOffsets.end())
+ return false;
+ BaseOffset = Known->second;
+ return true;
+ }
+};
+
/// EmptySubobjectMap - Keeps track of which empty subobjects exist at different
/// offsets while laying out a C++ class.
class EmptySubobjectMap {
@@ -541,7 +587,7 @@ protected:
/// \brief Whether the external AST source has provided a layout for this
/// record.
- unsigned ExternalLayout : 1;
+ unsigned UseExternalLayout : 1;
/// \brief Whether we need to infer alignment, even when we have an
/// externally-provided layout.
@@ -607,26 +653,14 @@ protected:
/// avoid visiting virtual bases more than once.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
- /// \brief Externally-provided size.
- uint64_t ExternalSize;
-
- /// \brief Externally-provided alignment.
- uint64_t ExternalAlign;
-
- /// \brief Externally-provided field offsets.
- llvm::DenseMap<const FieldDecl *, uint64_t> ExternalFieldOffsets;
-
- /// \brief Externally-provided direct, non-virtual base offsets.
- llvm::DenseMap<const CXXRecordDecl *, CharUnits> ExternalBaseOffsets;
-
- /// \brief Externally-provided virtual base offsets.
- llvm::DenseMap<const CXXRecordDecl *, CharUnits> ExternalVirtualBaseOffsets;
+ /// Valid if UseExternalLayout is true.
+ ExternalLayout External;
RecordLayoutBuilder(const ASTContext &Context,
EmptySubobjectMap *EmptySubobjects)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
- ExternalLayout(false), InferAlignment(false),
+ UseExternalLayout(false), InferAlignment(false),
Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
MaxFieldAlignment(CharUnits::Zero()),
@@ -748,8 +782,8 @@ protected:
void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
- RecordLayoutBuilder(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
- void operator=(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
+ RecordLayoutBuilder(const RecordLayoutBuilder &) = delete;
+ void operator=(const RecordLayoutBuilder &) = delete;
};
} // end anonymous namespace
@@ -1134,21 +1168,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
// Query the external layout to see if it provides an offset.
bool HasExternalLayout = false;
- if (ExternalLayout) {
+ if (UseExternalLayout) {
llvm::DenseMap<const CXXRecordDecl *, CharUnits>::iterator Known;
- if (Base->IsVirtual) {
- Known = ExternalVirtualBaseOffsets.find(Base->Class);
- if (Known != ExternalVirtualBaseOffsets.end()) {
- Offset = Known->second;
- HasExternalLayout = true;
- }
- } else {
- Known = ExternalBaseOffsets.find(Base->Class);
- if (Known != ExternalBaseOffsets.end()) {
- Offset = Known->second;
- HasExternalLayout = true;
- }
- }
+ if (Base->IsVirtual)
+ HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
+ else
+ HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
}
CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlignment();
@@ -1235,18 +1260,15 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
// If there is an external AST source, ask it for the various offsets.
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
- if (ExternalASTSource *External = Context.getExternalSource()) {
- ExternalLayout = External->layoutRecordType(RD,
- ExternalSize,
- ExternalAlign,
- ExternalFieldOffsets,
- ExternalBaseOffsets,
- ExternalVirtualBaseOffsets);
-
+ if (ExternalASTSource *Source = Context.getExternalSource()) {
+ UseExternalLayout = Source->layoutRecordType(
+ RD, External.Size, External.Align, External.FieldOffsets,
+ External.BaseOffsets, External.VirtualBaseOffsets);
+
// Update based on external alignment.
- if (ExternalLayout) {
- if (ExternalAlign > 0) {
- Alignment = Context.toCharUnitsFromBits(ExternalAlign);
+ if (UseExternalLayout) {
+ if (External.Align > 0) {
+ Alignment = Context.toCharUnitsFromBits(External.Align);
} else {
// The external source didn't have alignment information; infer it.
InferAlignment = true;
@@ -1588,7 +1610,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// If we're using external layout, give the external layout a chance
// to override this information.
- if (ExternalLayout)
+ if (UseExternalLayout)
FieldOffset = updateExternalFieldOffset(D, FieldOffset);
// Okay, place the bitfield at the calculated offset.
@@ -1604,7 +1626,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
FieldAlign = UnpackedFieldAlign = 1;
// Diagnose differences in layout due to padding or packing.
- if (!ExternalLayout)
+ if (!UseExternalLayout)
CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
UnpackedFieldAlign, FieldPacked, D);
@@ -1727,7 +1749,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D,
UnpackedFieldOffset =
UnpackedFieldOffset.RoundUpToAlignment(UnpackedFieldAlign);
- if (ExternalLayout) {
+ if (UseExternalLayout) {
FieldOffset = Context.toCharUnitsFromBits(
updateExternalFieldOffset(D, Context.toBits(FieldOffset)));
@@ -1750,7 +1772,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D,
// Place this field at the current location.
FieldOffsets.push_back(Context.toBits(FieldOffset));
- if (!ExternalLayout)
+ if (!UseExternalLayout)
CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset,
Context.toBits(UnpackedFieldOffset),
Context.toBits(UnpackedFieldAlign), FieldPacked, D);
@@ -1802,15 +1824,15 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
uint64_t RoundedSize
= llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment));
- if (ExternalLayout) {
+ if (UseExternalLayout) {
// If we're inferring alignment, and the external size is smaller than
// our size after we've rounded up to alignment, conservatively set the
// alignment to 1.
- if (InferAlignment && ExternalSize < RoundedSize) {
+ if (InferAlignment && External.Size < RoundedSize) {
Alignment = CharUnits::One();
InferAlignment = false;
}
- setSize(ExternalSize);
+ setSize(External.Size);
return;
}
@@ -1846,18 +1868,18 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment,
CharUnits UnpackedNewAlignment) {
// The alignment is not modified when using 'mac68k' alignment or when
// we have an externally-supplied layout that also provides overall alignment.
- if (IsMac68kAlign || (ExternalLayout && !InferAlignment))
+ if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
return;
if (NewAlignment > Alignment) {
- assert(llvm::isPowerOf2_32(NewAlignment.getQuantity() &&
- "Alignment not a power of 2"));
+ assert(llvm::isPowerOf2_64(NewAlignment.getQuantity()) &&
+ "Alignment not a power of 2");
Alignment = NewAlignment;
}
if (UnpackedNewAlignment > UnpackedAlignment) {
- assert(llvm::isPowerOf2_32(UnpackedNewAlignment.getQuantity() &&
- "Alignment not a power of 2"));
+ assert(llvm::isPowerOf2_64(UnpackedNewAlignment.getQuantity()) &&
+ "Alignment not a power of 2");
UnpackedAlignment = UnpackedNewAlignment;
}
}
@@ -1865,11 +1887,8 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment,
uint64_t
RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
uint64_t ComputedOffset) {
- assert(ExternalFieldOffsets.find(Field) != ExternalFieldOffsets.end() &&
- "Field does not have an external offset");
-
- uint64_t ExternalFieldOffset = ExternalFieldOffsets[Field];
-
+ uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
+
if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
// The externally-supplied field offset is before the field offset we
// computed. Assume that the structure is packed.
@@ -2152,9 +2171,8 @@ struct MicrosoftRecordLayoutBuilder {
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {}
private:
- MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &)
- LLVM_DELETED_FUNCTION;
- void operator=(const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
+ MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete;
+ void operator=(const MicrosoftRecordLayoutBuilder &) = delete;
public:
void layout(const RecordDecl *RD);
void cxxLayout(const CXXRecordDecl *RD);
@@ -2252,6 +2270,13 @@ public:
/// \brief True if this class is zero sized or first base is zero sized or
/// has this property. Only used for MS-ABI.
bool LeadsWithZeroSizedBase : 1;
+
+ /// \brief True if the external AST source provided a layout for this record.
+ bool UseExternalLayout : 1;
+
+ /// \brief The layout provided by the external AST source. Only active if
+ /// UseExternalLayout is true.
+ ExternalLayout External;
};
} // namespace
@@ -2354,8 +2379,9 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
// In 64-bit mode we always perform an alignment step after laying out vbases.
// In 32-bit mode we do not. The check to see if we need to perform alignment
// checks the RequiredAlignment field and performs alignment if it isn't 0.
- RequiredAlignment = Context.getTargetInfo().getPointerWidth(0) == 64 ?
- CharUnits::One() : CharUnits::Zero();
+ RequiredAlignment = Context.getTargetInfo().getTriple().isArch64Bit()
+ ? CharUnits::One()
+ : CharUnits::Zero();
// Compute the maximum field alignment.
MaxFieldAlignment = CharUnits::Zero();
// Honor the default struct packing maximum alignment flag.
@@ -2371,6 +2397,13 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
// Packed attribute forces max field alignment to be 1.
if (RD->hasAttr<PackedAttr>())
MaxFieldAlignment = CharUnits::One();
+
+ // Try to respect the external layout if present.
+ UseExternalLayout = false;
+ if (ExternalASTSource *Source = Context.getExternalSource())
+ UseExternalLayout = Source->layoutRecordType(
+ RD, External.Size, External.Align, External.FieldOffsets,
+ External.BaseOffsets, External.VirtualBaseOffsets);
}
void
@@ -2385,7 +2418,8 @@ MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {
// injection.
PointerInfo.Size =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- PointerInfo.Alignment = PointerInfo.Size;
+ PointerInfo.Alignment =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
// Respect pragma pack.
if (!MaxFieldAlignment.isZero())
PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
@@ -2475,7 +2509,18 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
BaseLayout.leadsWithZeroSizedBase())
Size++;
ElementInfo Info = getAdjustedElementInfo(BaseLayout);
- CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
+ CharUnits BaseOffset;
+
+ // Respect the external AST source base offset, if present.
+ bool FoundBase = false;
+ if (UseExternalLayout) {
+ FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
+ if (FoundBase)
+ assert(BaseOffset >= Size && "base offset already allocated");
+ }
+
+ if (!FoundBase)
+ BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
Bases.insert(std::make_pair(BaseDecl, BaseOffset));
Size = BaseOffset + BaseLayout.getNonVirtualSize();
PreviousBaseLayout = &BaseLayout;
@@ -2499,7 +2544,14 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
placeFieldAtOffset(CharUnits::Zero());
Size = std::max(Size, Info.Size);
} else {
- CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment);
+ CharUnits FieldOffset;
+ if (UseExternalLayout) {
+ FieldOffset =
+ Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
+ assert(FieldOffset >= Size && "field offset already allocated");
+ } else {
+ FieldOffset = Size.RoundUpToAlignment(Info.Alignment);
+ }
placeFieldAtOffset(FieldOffset);
Size = FieldOffset + Info.Size;
}
@@ -2573,14 +2625,16 @@ void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) {
CharUnits InjectionSite = VBPtrOffset;
// But before we do, make sure it's properly aligned.
VBPtrOffset = VBPtrOffset.RoundUpToAlignment(PointerInfo.Alignment);
+ // Shift everything after the vbptr down, unless we're using an external
+ // layout.
+ if (UseExternalLayout)
+ return;
// Determine where the first field should be laid out after the vbptr.
CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
// Make sure that the amount we push the fields back by is a multiple of the
// alignment.
CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment(
std::max(RequiredAlignment, Alignment));
- // Increase the size of the object and push back all fields by the offset
- // amount.
Size += Offset;
for (uint64_t &FieldOffset : FieldOffsets)
FieldOffset += Context.toBits(Offset);
@@ -2647,7 +2701,18 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
}
// Insert the virtual base.
ElementInfo Info = getAdjustedElementInfo(BaseLayout);
- CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
+ CharUnits BaseOffset;
+
+ // Respect the external AST source base offset, if present.
+ bool FoundBase = false;
+ if (UseExternalLayout) {
+ FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset);
+ if (FoundBase)
+ assert(BaseOffset >= Size && "base offset already allocated");
+ }
+ if (!FoundBase)
+ BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
+
VBases.insert(std::make_pair(BaseDecl,
ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
Size = BaseOffset + BaseLayout.getNonVirtualSize();
@@ -2677,6 +2742,12 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
else
Size = MinEmptyStructSize;
}
+
+ if (UseExternalLayout) {
+ Size = Context.toCharUnitsFromBits(External.Size);
+ if (External.Align)
+ Alignment = Context.toCharUnitsFromBits(External.Align);
+ }
}
// Recursively walks the non-virtual bases of a class and determines if any of
@@ -2815,7 +2886,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
const ASTRecordLayout *NewEntry = nullptr;
- if (isMsLayout(D) && !D->getASTContext().getExternalSource()) {
+ if (isMsLayout(D)) {
NewEntry = BuildMicrosoftASTRecordLayout(D);
} else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
EmptySubobjectMap EmptySubobjects(*this, RD);
@@ -2905,11 +2976,11 @@ void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) {
// Look up the cache entry. Since we're working with the first
// declaration, its parent must be the class definition, which is
// the correct key for the KeyFunctions hash.
- llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr>::iterator
- I = KeyFunctions.find(Method->getParent());
+ const auto &Map = KeyFunctions;
+ auto I = Map.find(Method->getParent());
// If it's not cached, there's nothing to do.
- if (I == KeyFunctions.end()) return;
+ if (I == Map.end()) return;
// If it is cached, check whether it's the target method, and if so,
// remove it from the cache. Note, the call to 'get' might invalidate
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 68c7e7278432..6baa99bbc5bf 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -95,10 +95,16 @@ void Stmt::EnableStatistics() {
Stmt *Stmt::IgnoreImplicit() {
Stmt *s = this;
- if (ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(s))
+ if (auto *ewc = dyn_cast<ExprWithCleanups>(s))
s = ewc->getSubExpr();
- while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(s))
+ if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
+ s = mte->GetTemporaryExpr();
+
+ if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s))
+ s = bte->getSubExpr();
+
+ while (auto *ice = dyn_cast<ImplicitCastExpr>(s))
s = ice->getSubExpr();
return s;
@@ -934,8 +940,7 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
}
SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond)
- : Stmt(SwitchStmtClass), FirstCase(nullptr), AllEnumCasesCovered(0)
-{
+ : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {
setConditionVariable(C, Var);
SubExprs[COND] = cond;
SubExprs[BODY] = nullptr;
@@ -1241,17 +1246,47 @@ OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPFirstprivateClause(N);
}
-OMPLastprivateClause *OMPLastprivateClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) {
+ assert(PrivateCopies.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end());
+}
+
+void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end());
+}
+
+void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPLastprivateClause *OMPLastprivateClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 5 * sizeof(Expr *) * VL.size());
OMPLastprivateClause *Clause =
new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
@@ -1259,7 +1294,7 @@ OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 5 * sizeof(Expr *) * N);
return new (Mem) OMPLastprivateClause(N);
}
@@ -1285,27 +1320,56 @@ OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPSharedClause(N);
}
-OMPLinearClause *OMPLinearClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL, Expr *Step) {
+void OMPLinearClause::setInits(ArrayRef<Expr *> IL) {
+ assert(IL.size() == varlist_size() &&
+ "Number of inits is not the same as the preallocated buffer");
+ std::copy(IL.begin(), IL.end(), varlist_end());
+}
+
+void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) {
+ assert(UL.size() == varlist_size() &&
+ "Number of updates is not the same as the preallocated buffer");
+ std::copy(UL.begin(), UL.end(), getInits().end());
+}
+
+void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) {
+ assert(FL.size() == varlist_size() &&
+ "Number of final updates is not the same as the preallocated buffer");
+ std::copy(FL.begin(), FL.end(), getUpdates().end());
+}
+
+OMPLinearClause *
+OMPLinearClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) {
+ // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
+ // (Step and CalcStep).
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * (VL.size() + 1));
+ (4 * VL.size() + 2) * sizeof(Expr *));
OMPLinearClause *Clause = new (Mem)
OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setInits(IL);
+ // Fill update and final expressions with zeroes, they are provided later,
+ // after the directive construction.
+ std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(),
+ nullptr);
+ std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(),
+ nullptr);
Clause->setStep(Step);
+ Clause->setCalcStep(CalcStep);
return Clause;
}
OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
unsigned NumVars) {
+ // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
+ // (Step and CalcStep).
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * (NumVars + 1));
+ (4 * NumVars + 2) * sizeof(Expr *));
return new (Mem) OMPLinearClause(NumVars);
}
@@ -1331,17 +1395,41 @@ OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPAlignedClause(NumVars);
}
-OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
+}
+
+void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPCopyinClause *OMPCopyinClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 4 * sizeof(Expr *) * VL.size());
OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc,
EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
@@ -1349,21 +1437,45 @@ OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 4 * sizeof(Expr *) * N);
return new (Mem) OMPCopyinClause(N);
}
-OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
+}
+
+void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPCopyprivateClause *OMPCopyprivateClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 4 * sizeof(Expr *) * VL.size());
OMPCopyprivateClause *Clause =
new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
@@ -1371,7 +1483,7 @@ OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 4 * sizeof(Expr *) * N);
return new (Mem) OMPCopyprivateClause(N);
}
@@ -1399,16 +1511,42 @@ void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) {
std::copy(A.begin(), A.end(), getFinals().begin());
}
+void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
+ assert(
+ LHSExprs.size() == varlist_size() &&
+ "Number of LHS expressions is not the same as the preallocated buffer");
+ std::copy(LHSExprs.begin(), LHSExprs.end(), varlist_end());
+}
+
+void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
+ assert(
+ RHSExprs.size() == varlist_size() &&
+ "Number of RHS expressions is not the same as the preallocated buffer");
+ std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
+}
+
+void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
+ assert(ReductionOps.size() == varlist_size() && "Number of reduction "
+ "expressions is not the same "
+ "as the preallocated buffer");
+ std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
+}
+
OMPReductionClause *OMPReductionClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
- NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) {
+ NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
+ ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
+ ArrayRef<Expr *> ReductionOps) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
+ 4 * sizeof(Expr *) * VL.size());
OMPReductionClause *Clause = new (Mem) OMPReductionClause(
StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
Clause->setVarRefs(VL);
+ Clause->setLHSExprs(LHSExprs);
+ Clause->setRHSExprs(RHSExprs);
+ Clause->setReductionOps(ReductionOps);
return Clause;
}
@@ -1416,7 +1554,7 @@ OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 4 * sizeof(Expr *) * N);
return new (Mem) OMPReductionClause(N);
}
@@ -1443,10 +1581,7 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
const OMPClause *
OMPExecutableDirective::getSingleClause(OpenMPClauseKind K) const {
- auto ClauseFilter =
- [=](const OMPClause *C) -> bool { return C->getClauseKind() == K; };
- OMPExecutableDirective::filtered_clause_iterator<decltype(ClauseFilter)> I(
- clauses(), ClauseFilter);
+ auto &&I = getClausesOfKind(K);
if (I) {
auto *Clause = *I;
@@ -1948,14 +2083,14 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPOrderedDirective();
}
-OMPAtomicDirective *
-OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E) {
+OMPAtomicDirective *OMPAtomicDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
+ Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
llvm::alignOf<OMPClause *>());
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- 4 * sizeof(Stmt *));
+ 5 * sizeof(Stmt *));
OMPAtomicDirective *Dir =
new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
@@ -1963,6 +2098,9 @@ OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc,
Dir->setX(X);
Dir->setV(V);
Dir->setExpr(E);
+ Dir->setUpdateExpr(UE);
+ Dir->IsXLHSInRHSPart = IsXLHSInRHSPart;
+ Dir->IsPostfixUpdate = IsPostfixUpdate;
return Dir;
}
@@ -1972,7 +2110,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
llvm::alignOf<OMPClause *>());
void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 4 * sizeof(Stmt *));
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *));
return new (Mem) OMPAtomicDirective(NumClauses);
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 927a679244b5..dc4f9964c7a6 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1069,7 +1069,8 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
// Emit suffixes. Integer literals are always a builtin integer type.
switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
default: llvm_unreachable("Unexpected type for integer literal!");
- case BuiltinType::SChar: OS << "i8"; break;
+ case BuiltinType::Char_S:
+ case BuiltinType::Char_U: OS << "i8"; break;
case BuiltinType::UChar: OS << "Ui8"; break;
case BuiltinType::Short: OS << "i16"; break;
case BuiltinType::UShort: OS << "Ui16"; break;
@@ -1373,24 +1374,24 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
return;
}
- OS << "{ ";
+ OS << "{";
for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
if (i) OS << ", ";
if (Node->getInit(i))
PrintExpr(Node->getInit(i));
else
- OS << "0";
+ OS << "{}";
}
- OS << " }";
+ OS << "}";
}
void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
- OS << "( ";
+ OS << "(";
for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
if (i) OS << ", ";
PrintExpr(Node->getExpr(i));
}
- OS << " )";
+ OS << ")";
}
void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
@@ -1621,6 +1622,15 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
const TemplateArgumentList *Args =
cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs();
assert(Args);
+
+ if (Args->size() != 1) {
+ OS << "operator \"\" " << Node->getUDSuffix()->getName();
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, Args->data(), Args->size(), Policy);
+ OS << "()";
+ return;
+ }
+
const TemplateArgument &Pack = Args->get(0);
for (const auto &P : Pack.pack_elements()) {
char C = (char)P.getAsIntegral().getZExtValue();
@@ -1679,9 +1689,13 @@ void StmtPrinter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
Node->getType().print(OS, Policy);
- OS << "(";
+ // If there are no parens, this is list-initialization, and the braces are
+ // part of the syntax of the inner construct.
+ if (Node->getLParenLoc().isValid())
+ OS << "(";
PrintExpr(Node->getSubExpr());
- OS << ")";
+ if (Node->getLParenLoc().isValid())
+ OS << ")";
}
void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
@@ -1690,7 +1704,12 @@ void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
Node->getType().print(OS, Policy);
- OS << "(";
+ if (Node->isStdInitListInitialization())
+ /* Nothing to do; braces are part of creating the std::initializer_list. */;
+ else if (Node->isListInitialization())
+ OS << "{";
+ else
+ OS << "(";
for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
ArgEnd = Node->arg_end();
Arg != ArgEnd; ++Arg) {
@@ -1700,7 +1719,12 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
OS << ", ";
PrintExpr(*Arg);
}
- OS << ")";
+ if (Node->isStdInitListInitialization())
+ /* See above. */;
+ else if (Node->isListInitialization())
+ OS << "}";
+ else
+ OS << ")";
}
void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
@@ -1734,7 +1758,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
break;
case LCK_ByRef:
- if (Node->getCaptureDefault() != LCD_ByRef || C->isInitCapture())
+ if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(C))
OS << '&';
OS << C->getCapturedVar()->getName();
break;
@@ -1746,7 +1770,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
llvm_unreachable("VLA type in explicit captures.");
}
- if (C->isInitCapture())
+ if (Node->isInitCapture(C))
PrintExpr(C->getCapturedVar()->getInit());
}
OS << ']';
@@ -1866,8 +1890,8 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
}
void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
- if (E->isListInitialization())
- OS << "{ ";
+ if (E->isListInitialization() && !E->isStdInitListInitialization())
+ OS << "{";
for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
if (isa<CXXDefaultArgExpr>(E->getArg(i))) {
@@ -1879,8 +1903,8 @@ void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
PrintExpr(E->getArg(i));
}
- if (E->isListInitialization())
- OS << " }";
+ if (E->isListInitialization() && !E->isStdInitListInitialization())
+ OS << "}";
}
void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index d1f25d63b3f9..c66b153eadbb 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -298,8 +298,12 @@ void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
- if (C->getChunkSize())
+ if (C->getChunkSize()) {
Profiler->VisitStmt(C->getChunkSize());
+ if (C->getHelperChunkSize()) {
+ Profiler->VisitStmt(C->getChunkSize());
+ }
+ }
}
void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *) {}
@@ -346,6 +350,15 @@ OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) {
void
OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
VisitOMPClauseList(C);
@@ -356,10 +369,29 @@ void OMPClauseProfiler::VisitOMPReductionClause(
C->getQualifierLoc().getNestedNameSpecifier());
Profiler->VisitName(C->getNameInfo().getName());
VisitOMPClauseList(C);
+ for (auto *E : C->lhs_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->rhs_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->reduction_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->inits()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->updates()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->finals()) {
+ Profiler->VisitStmt(E);
+ }
Profiler->VisitStmt(C->getStep());
+ Profiler->VisitStmt(C->getCalcStep());
}
void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) {
VisitOMPClauseList(C);
@@ -367,10 +399,28 @@ void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) {
}
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void
OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) {
VisitOMPClauseList(C);
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index e4f364d04f86..09bb7692596c 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -170,15 +170,7 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
VectorKind vecKind)
- : Type(Vector, canonType, vecType->isDependentType(),
- vecType->isInstantiationDependentType(),
- vecType->isVariablyModifiedType(),
- vecType->containsUnexpandedParameterPack()),
- ElementType(vecType)
-{
- VectorTypeBits.VecKind = vecKind;
- VectorTypeBits.NumElements = nElements;
-}
+ : VectorType(Vector, vecType, nElements, canonType, vecKind) {}
VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
QualType canonType, VectorKind vecKind)
@@ -640,12 +632,13 @@ bool Type::hasIntegerRepresentation() const {
bool Type::isIntegralType(ASTContext &Ctx) const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
- BT->getKind() <= BuiltinType::Int128;
-
+ BT->getKind() <= BuiltinType::Int128;
+
+ // Complete enum types are integral in C.
if (!Ctx.getLangOpts().CPlusPlus)
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
- return ET->getDecl()->isComplete(); // Complete enum types are integral in C.
-
+ return ET->getDecl()->isComplete();
+
return false;
}
@@ -736,7 +729,7 @@ bool Type::isSignedIntegerType() const {
bool Type::isSignedIntegerOrEnumerationType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
- BT->getKind() <= BuiltinType::Int128;
+ BT->getKind() <= BuiltinType::Int128;
}
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
@@ -1089,7 +1082,7 @@ bool QualType::isTrivialType(ASTContext &Context) const {
bool QualType::isTriviallyCopyableType(ASTContext &Context) const {
if ((*this)->isArrayType())
- return Context.getBaseElementType(*this).isTrivialType(Context);
+ return Context.getBaseElementType(*this).isTriviallyCopyableType(Context);
if (Context.getLangOpts().ObjCAutoRefCount) {
switch (getObjCLifetime()) {
@@ -1586,8 +1579,9 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86_64SysV: return "sysv_abi";
case CC_AAPCS: return "aapcs";
case CC_AAPCS_VFP: return "aapcs-vfp";
- case CC_PnaclCall: return "pnaclcall";
case CC_IntelOclBicc: return "intel_ocl_bicc";
+ case CC_SpirFunction: return "spir_function";
+ case CC_SpirKernel: return "spir_kernel";
}
llvm_unreachable("Invalid calling convention.");
@@ -1720,7 +1714,7 @@ bool FunctionProtoType::isNothrow(const ASTContext &Ctx,
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
return true;
- if (EST == EST_Dynamic && ResultIfDependent == true) {
+ if (EST == EST_Dynamic && ResultIfDependent) {
// A dynamic exception specification is throwing unless every exception
// type is an (unexpanded) pack expansion type.
for (unsigned I = 0, N = NumExceptions; I != N; ++I)
@@ -1936,7 +1930,6 @@ bool AttributedType::isCallingConv() const {
case attr_pascal:
case attr_ms_abi:
case attr_sysv_abi:
- case attr_pnaclcall:
case attr_inteloclbicc:
return true;
}
@@ -2378,6 +2371,11 @@ bool Type::isObjCNSObjectType() const {
return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
return false;
}
+bool Type::isObjCIndependentClassType() const {
+ if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+ return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
+ return false;
+}
bool Type::isObjCRetainableType() const {
return isObjCObjectPointerType() ||
isBlockPointerType() ||
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index e36fc175c449..3928fe8f8942 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -110,7 +110,7 @@ namespace {
};
}
-static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals) {
+static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, bool C99) {
bool appendSpace = false;
if (TypeQuals & Qualifiers::Const) {
OS << "const";
@@ -123,7 +123,11 @@ static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals) {
}
if (TypeQuals & Qualifiers::Restrict) {
if (appendSpace) OS << ' ';
- OS << "restrict";
+ if (C99) {
+ OS << "restrict";
+ } else {
+ OS << "__restrict";
+ }
}
}
@@ -432,7 +436,7 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers());
+ AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99);
OS << ' ';
}
@@ -465,7 +469,7 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers());
+ AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99);
OS << ' ';
}
@@ -685,9 +689,6 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_AAPCS_VFP:
OS << " __attribute__((pcs(\"aapcs-vfp\")))";
break;
- case CC_PnaclCall:
- OS << " __attribute__((pnaclcall))";
- break;
case CC_IntelOclBicc:
OS << " __attribute__((intel_ocl_bicc))";
break;
@@ -697,6 +698,10 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_X86_64SysV:
OS << " __attribute__((sysv_abi))";
break;
+ case CC_SpirFunction:
+ case CC_SpirKernel:
+ // Do nothing. These CCs are not available as attributes.
+ break;
}
}
@@ -708,7 +713,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
if (unsigned quals = T->getTypeQuals()) {
OS << ' ';
- AppendTypeQualList(OS, quals);
+ AppendTypeQualList(OS, quals, Policy.LangOpts.C99);
}
switch (T->getRefQualifier()) {
@@ -1253,7 +1258,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
OS << ')';
break;
}
- case AttributedType::attr_pnaclcall: OS << "pnaclcall"; break;
case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
}
OS << "))";
@@ -1473,7 +1477,7 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
unsigned quals = getCVRQualifiers();
if (quals) {
- AppendTypeQualList(OS, quals);
+ AppendTypeQualList(OS, quals, Policy.LangOpts.C99);
addSpace = true;
}
if (unsigned addrspace = getAddressSpace()) {
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index ddb1f057ac8e..ca5f0aad0013 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -13,9 +13,11 @@
#include "clang/AST/VTableBuilder.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -216,7 +218,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
#endif
}
-static BaseOffset ComputeBaseOffset(ASTContext &Context,
+static BaseOffset ComputeBaseOffset(const ASTContext &Context,
const CXXRecordDecl *DerivedRD,
const CXXBasePath &Path) {
CharUnits NonVirtualOffset = CharUnits::Zero();
@@ -255,7 +257,7 @@ static BaseOffset ComputeBaseOffset(ASTContext &Context,
}
-static BaseOffset ComputeBaseOffset(ASTContext &Context,
+static BaseOffset ComputeBaseOffset(const ASTContext &Context,
const CXXRecordDecl *BaseRD,
const CXXRecordDecl *DerivedRD) {
CXXBasePaths Paths(/*FindAmbiguities=*/false,
@@ -411,7 +413,8 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
for (const auto *MD : RD->methods()) {
if (!MD->isVirtual())
continue;
-
+ MD = MD->getCanonicalDecl();
+
OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset());
Out << " ";
@@ -695,6 +698,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
for (const auto *MD : RD->methods()) {
if (!MD->isVirtual())
continue;
+ MD = MD->getCanonicalDecl();
CharUnits OffsetOffset = getCurrentOffsetOffset();
@@ -1514,6 +1518,7 @@ void ItaniumVTableBuilder::AddMethods(
for (const auto *MD : RD->methods()) {
if (!MD->isVirtual())
continue;
+ MD = MD->getCanonicalDecl();
// Get the final overrider.
FinalOverriders::OverriderInfo Overrider =
@@ -2196,6 +2201,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
// We only want virtual member functions.
if (!MD->isVirtual())
continue;
+ MD = MD->getCanonicalDecl();
std::string MethodName =
PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
@@ -2585,7 +2591,9 @@ public:
// Only include the RTTI component if we know that we will provide a
// definition of the vftable.
HasRTTIComponent = Context.getLangOpts().RTTIData &&
- !MostDerivedClass->hasAttr<DLLImportAttr>();
+ !MostDerivedClass->hasAttr<DLLImportAttr>() &&
+ MostDerivedClass->getTemplateSpecializationKind() !=
+ TSK_ExplicitInstantiationDeclaration;
LayoutVFTable();
@@ -2625,8 +2633,6 @@ public:
void dumpLayout(raw_ostream &);
};
-} // end namespace
-
/// InitialOverriddenDefinitionCollector - Finds the set of least derived bases
/// that define the given method.
struct InitialOverriddenDefinitionCollector {
@@ -2641,6 +2647,8 @@ struct InitialOverriddenDefinitionCollector {
}
};
+} // end namespace
+
static bool BaseInSet(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, void *BasesSet) {
BasesSetVectorTy *Bases = (BasesSetVectorTy *)BasesSet;
@@ -2730,8 +2738,9 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
CharUnits ThisOffset = Overrider.Offset;
CharUnits LastVBaseOffset;
- // For each path from the overrider to the parents of the overridden methods,
- // traverse the path, calculating the this offset in the most derived class.
+ // For each path from the overrider to the parents of the overridden
+ // methods, traverse the path, calculating the this offset in the most
+ // derived class.
for (int J = 0, F = Path.size(); J != F; ++J) {
const CXXBasePathElement &Element = Path[J];
QualType CurTy = Element.Base->getType();
@@ -2930,6 +2939,7 @@ static void GroupNewVirtualOverloads(
typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
VisitedGroupIndicesTy VisitedGroupIndices;
for (const auto *MD : RD->methods()) {
+ MD = MD->getCanonicalDecl();
VisitedGroupIndicesTy::iterator J;
bool Inserted;
std::tie(J, Inserted) = VisitedGroupIndices.insert(
@@ -2962,7 +2972,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
// See if this class expands a vftable of the base we look at, which is either
- // the one defined by the vfptr base path or the primary base of the current class.
+ // the one defined by the vfptr base path or the primary base of the current
+ // class.
const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
CharUnits NextBaseOffset;
if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
@@ -3020,7 +3031,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
ThisAdjustmentOffset);
if (OverriddenMD) {
- // If MD overrides anything in this vftable, we need to update the entries.
+ // If MD overrides anything in this vftable, we need to update the
+ // entries.
MethodInfoMapTy::iterator OverriddenMDIterator =
MethodInfoMap.find(OverriddenMD);
@@ -3435,55 +3447,176 @@ MicrosoftVTableContext::~MicrosoftVTableContext() {
llvm::DeleteContainerSeconds(VBaseInfo);
}
-static bool
-findPathForVPtr(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout,
- const CXXRecordDecl *RD, CharUnits Offset,
- llvm::SmallPtrSetImpl<const CXXRecordDecl *> &VBasesSeen,
- VPtrInfo::BasePath &FullPath, VPtrInfo *Info) {
- if (RD == Info->BaseWithVPtr && Offset == Info->FullOffsetInMDC) {
- Info->PathToBaseWithVPtr = FullPath;
- return true;
+namespace {
+typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
+ llvm::DenseSet<BaseSubobject>> FullPathTy;
+}
+
+// This recursive function finds all paths from a subobject centered at
+// (RD, Offset) to the subobject located at BaseWithVPtr.
+static void findPathsToSubobject(ASTContext &Context,
+ const ASTRecordLayout &MostDerivedLayout,
+ const CXXRecordDecl *RD, CharUnits Offset,
+ BaseSubobject BaseWithVPtr,
+ FullPathTy &FullPath,
+ std::list<FullPathTy> &Paths) {
+ if (BaseSubobject(RD, Offset) == BaseWithVPtr) {
+ Paths.push_back(FullPath);
+ return;
}
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- // Recurse with non-virtual bases first.
- // FIXME: Does this need to be in layout order? Virtual bases will be in base
- // specifier order, which isn't necessarily layout order.
- SmallVector<CXXBaseSpecifier, 4> Bases(RD->bases_begin(), RD->bases_end());
- std::stable_partition(Bases.begin(), Bases.end(),
- [](CXXBaseSpecifier bs) { return !bs.isVirtual(); });
-
- for (const auto &B : Bases) {
- const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
- CharUnits NewOffset;
- if (!B.isVirtual())
- NewOffset = Offset + Layout.getBaseClassOffset(Base);
- else {
- if (!VBasesSeen.insert(Base).second)
- return false;
- NewOffset = MostDerivedLayout.getVBaseClassOffset(Base);
- }
- FullPath.push_back(Base);
- if (findPathForVPtr(Context, MostDerivedLayout, Base, NewOffset, VBasesSeen,
- FullPath, Info))
- return true;
+ for (const CXXBaseSpecifier &BS : RD->bases()) {
+ const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
+ CharUnits NewOffset = BS.isVirtual()
+ ? MostDerivedLayout.getVBaseClassOffset(Base)
+ : Offset + Layout.getBaseClassOffset(Base);
+ FullPath.insert(BaseSubobject(Base, NewOffset));
+ findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset,
+ BaseWithVPtr, FullPath, Paths);
FullPath.pop_back();
}
- return false;
+}
+
+// Return the paths which are not subsets of other paths.
+static void removeRedundantPaths(std::list<FullPathTy> &FullPaths) {
+ FullPaths.remove_if([&](const FullPathTy &SpecificPath) {
+ for (const FullPathTy &OtherPath : FullPaths) {
+ if (&SpecificPath == &OtherPath)
+ continue;
+ if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
+ [&](const BaseSubobject &BSO) {
+ return OtherPath.count(BSO) != 0;
+ })) {
+ return true;
+ }
+ }
+ return false;
+ });
+}
+
+static CharUnits getOffsetOfFullPath(ASTContext &Context,
+ const CXXRecordDecl *RD,
+ const FullPathTy &FullPath) {
+ const ASTRecordLayout &MostDerivedLayout =
+ Context.getASTRecordLayout(RD);
+ CharUnits Offset = CharUnits::fromQuantity(-1);
+ for (const BaseSubobject &BSO : FullPath) {
+ const CXXRecordDecl *Base = BSO.getBase();
+ // The first entry in the path is always the most derived record, skip it.
+ if (Base == RD) {
+ assert(Offset.getQuantity() == -1);
+ Offset = CharUnits::Zero();
+ continue;
+ }
+ assert(Offset.getQuantity() != -1);
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ // While we know which base has to be traversed, we don't know if that base
+ // was a virtual base.
+ const CXXBaseSpecifier *BaseBS = std::find_if(
+ RD->bases_begin(), RD->bases_end(), [&](const CXXBaseSpecifier &BS) {
+ return BS.getType()->getAsCXXRecordDecl() == Base;
+ });
+ Offset = BaseBS->isVirtual() ? MostDerivedLayout.getVBaseClassOffset(Base)
+ : Offset + Layout.getBaseClassOffset(Base);
+ RD = Base;
+ }
+ return Offset;
+}
+
+// We want to select the path which introduces the most covariant overrides. If
+// two paths introduce overrides which the other path doesn't contain, issue a
+// diagnostic.
+static const FullPathTy *selectBestPath(ASTContext &Context,
+ const CXXRecordDecl *RD, VPtrInfo *Info,
+ std::list<FullPathTy> &FullPaths) {
+ // Handle some easy cases first.
+ if (FullPaths.empty())
+ return nullptr;
+ if (FullPaths.size() == 1)
+ return &FullPaths.front();
+
+ const FullPathTy *BestPath = nullptr;
+ typedef std::set<const CXXMethodDecl *> OverriderSetTy;
+ OverriderSetTy LastOverrides;
+ for (const FullPathTy &SpecificPath : FullPaths) {
+ assert(!SpecificPath.empty());
+ OverriderSetTy CurrentOverrides;
+ const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
+ // Find the distance from the start of the path to the subobject with the
+ // VPtr.
+ CharUnits BaseOffset =
+ getOffsetOfFullPath(Context, TopLevelRD, SpecificPath);
+ FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD);
+ for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) {
+ if (!MD->isVirtual())
+ continue;
+ FinalOverriders::OverriderInfo OI =
+ Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
+ const CXXMethodDecl *OverridingMethod = OI.Method;
+ // Only overriders which have a return adjustment introduce problematic
+ // thunks.
+ if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
+ .isEmpty())
+ continue;
+ // It's possible that the overrider isn't in this path. If so, skip it
+ // because this path didn't introduce it.
+ const CXXRecordDecl *OverridingParent = OverridingMethod->getParent();
+ if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
+ [&](const BaseSubobject &BSO) {
+ return BSO.getBase() == OverridingParent;
+ }))
+ continue;
+ CurrentOverrides.insert(OverridingMethod);
+ }
+ OverriderSetTy NewOverrides =
+ llvm::set_difference(CurrentOverrides, LastOverrides);
+ if (NewOverrides.empty())
+ continue;
+ OverriderSetTy MissingOverrides =
+ llvm::set_difference(LastOverrides, CurrentOverrides);
+ if (MissingOverrides.empty()) {
+ // This path is a strict improvement over the last path, let's use it.
+ BestPath = &SpecificPath;
+ std::swap(CurrentOverrides, LastOverrides);
+ } else {
+ // This path introduces an overrider with a conflicting covariant thunk.
+ DiagnosticsEngine &Diags = Context.getDiagnostics();
+ const CXXMethodDecl *CovariantMD = *NewOverrides.begin();
+ const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
+ Diags.Report(RD->getLocation(), diag::err_vftable_ambiguous_component)
+ << RD;
+ Diags.Report(CovariantMD->getLocation(), diag::note_covariant_thunk)
+ << CovariantMD;
+ Diags.Report(ConflictMD->getLocation(), diag::note_covariant_thunk)
+ << ConflictMD;
+ }
+ }
+ // Go with the path that introduced the most covariant overrides. If there is
+ // no such path, pick the first path.
+ return BestPath ? BestPath : &FullPaths.front();
}
static void computeFullPathsForVFTables(ASTContext &Context,
const CXXRecordDecl *RD,
VPtrInfoVector &Paths) {
- llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
- VPtrInfo::BasePath FullPath;
+ FullPathTy FullPath;
+ std::list<FullPathTy> FullPaths;
for (VPtrInfo *Info : Paths) {
- findPathForVPtr(Context, MostDerivedLayout, RD, CharUnits::Zero(),
- VBasesSeen, FullPath, Info);
- VBasesSeen.clear();
+ findPathsToSubobject(
+ Context, MostDerivedLayout, RD, CharUnits::Zero(),
+ BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
+ FullPaths);
FullPath.clear();
+ removeRedundantPaths(FullPaths);
+ Info->PathToBaseWithVPtr.clear();
+ if (const FullPathTy *BestPath =
+ selectBestPath(Context, RD, Info, FullPaths))
+ for (const BaseSubobject &BSO : *BestPath)
+ Info->PathToBaseWithVPtr.push_back(BSO.getBase());
+ FullPaths.clear();
}
}