summaryrefslogtreecommitdiffstats
path: root/lib/AST
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
committerdim <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
commit056abd2059c65a3e908193aeae16fad98017437c (patch)
tree2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /lib/AST
parentcc73504950eb7b5dff2dded9bedd67bc36d64641 (diff)
downloadFreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip
FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTConsumer.cpp5
-rw-r--r--lib/AST/ASTContext.cpp325
-rw-r--r--lib/AST/ASTDiagnostic.cpp277
-rw-r--r--lib/AST/ASTImporter.cpp478
-rw-r--r--lib/AST/CMakeLists.txt3
-rw-r--r--lib/AST/CXXInheritance.cpp32
-rw-r--r--lib/AST/Comment.cpp93
-rw-r--r--lib/AST/CommentBriefParser.cpp51
-rw-r--r--lib/AST/CommentCommandTraits.cpp141
-rw-r--r--lib/AST/CommentDumper.cpp48
-rw-r--r--lib/AST/CommentLexer.cpp62
-rw-r--r--lib/AST/CommentParser.cpp72
-rw-r--r--lib/AST/CommentSema.cpp314
-rw-r--r--lib/AST/Decl.cpp88
-rw-r--r--lib/AST/DeclBase.cpp2
-rw-r--r--lib/AST/DeclCXX.cpp30
-rw-r--r--lib/AST/DeclObjC.cpp269
-rw-r--r--lib/AST/DeclPrinter.cpp18
-rw-r--r--lib/AST/DeclTemplate.cpp86
-rw-r--r--lib/AST/DumpXML.cpp23
-rw-r--r--lib/AST/Expr.cpp299
-rw-r--r--lib/AST/ExprCXX.cpp121
-rw-r--r--lib/AST/ExprClassification.cpp1
-rw-r--r--lib/AST/ExprConstant.cpp61
-rw-r--r--lib/AST/ItaniumMangle.cpp133
-rw-r--r--lib/AST/MicrosoftMangle.cpp242
-rw-r--r--lib/AST/NSAPI.cpp1
-rw-r--r--lib/AST/ParentMap.cpp69
-rw-r--r--lib/AST/RawCommentList.cpp69
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp84
-rw-r--r--lib/AST/Stmt.cpp167
-rw-r--r--lib/AST/StmtDumper.cpp115
-rw-r--r--lib/AST/StmtPrinter.cpp68
-rw-r--r--lib/AST/StmtProfile.cpp16
-rw-r--r--lib/AST/TemplateBase.cpp63
-rw-r--r--lib/AST/Type.cpp55
-rw-r--r--lib/AST/TypeLoc.cpp55
-rw-r--r--lib/AST/TypePrinter.cpp14
-rw-r--r--lib/AST/VTableBuilder.cpp3
39 files changed, 2855 insertions, 1198 deletions
diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp
index 1672bc8..a4e17c0 100644
--- a/lib/AST/ASTConsumer.cpp
+++ b/lib/AST/ASTConsumer.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Decl.h"
using namespace clang;
bool ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {
@@ -24,3 +25,7 @@ void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
}
void ASTConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {}
+
+void ASTConsumer::HandleImplicitImportDecl(ImportDecl *D) {
+ HandleTopLevelDecl(DeclGroupRef(D));
+}
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index c021323..74c68ae 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Mangle.h"
+#include "clang/AST/Comment.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -72,6 +73,22 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
return NULL;
}
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->isStaticDataMember() &&
+ VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ return NULL;
+ }
+
+ if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
+ if (CRD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ return NULL;
+ }
+
+ if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+ if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ return NULL;
+ }
+
// TODO: handle comments for function parameters properly.
if (isa<ParmVarDecl>(D))
return NULL;
@@ -196,15 +213,72 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
namespace {
/// If we have a 'templated' declaration for a template, adjust 'D' to
/// refer to the actual template.
+/// If we have an implicit instantiation, adjust 'D' to refer to template.
const Decl *adjustDeclToTemplate(const Decl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // Is this function declaration part of a function template?
if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
- D = FTD;
- } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (const ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
- D = CTD;
+ return FTD;
+
+ // Nothing to do if function is not an implicit instantiation.
+ if (FD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
+ return D;
+
+ // Function is an implicit instantiation of a function template?
+ if (const FunctionTemplateDecl *FTD = FD->getPrimaryTemplate())
+ return FTD;
+
+ // Function is instantiated from a member definition of a class template?
+ if (const FunctionDecl *MemberDecl =
+ FD->getInstantiatedFromMemberFunction())
+ return MemberDecl;
+
+ return D;
}
- // FIXME: Alias templates?
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ // Static data member is instantiated from a member definition of a class
+ // template?
+ if (VD->isStaticDataMember())
+ if (const VarDecl *MemberDecl = VD->getInstantiatedFromStaticDataMember())
+ return MemberDecl;
+
+ return D;
+ }
+ if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
+ // Is this class declaration part of a class template?
+ if (const ClassTemplateDecl *CTD = CRD->getDescribedClassTemplate())
+ return CTD;
+
+ // Class is an implicit instantiation of a class template or partial
+ // specialization?
+ if (const ClassTemplateSpecializationDecl *CTSD =
+ dyn_cast<ClassTemplateSpecializationDecl>(CRD)) {
+ if (CTSD->getSpecializationKind() != TSK_ImplicitInstantiation)
+ return D;
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ PU = CTSD->getSpecializedTemplateOrPartial();
+ return PU.is<ClassTemplateDecl*>() ?
+ static_cast<const Decl*>(PU.get<ClassTemplateDecl *>()) :
+ static_cast<const Decl*>(
+ PU.get<ClassTemplatePartialSpecializationDecl *>());
+ }
+
+ // Class is instantiated from a member definition of a class template?
+ if (const MemberSpecializationInfo *Info =
+ CRD->getMemberSpecializationInfo())
+ return Info->getInstantiatedFrom();
+
+ return D;
+ }
+ if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+ // Enum is instantiated from a member definition of a class template?
+ if (const EnumDecl *MemberDecl = ED->getInstantiatedFromMemberEnum())
+ return MemberDecl;
+
+ return D;
+ }
+ // FIXME: Adjust alias templates?
return D;
}
} // unnamed namespace
@@ -282,23 +356,83 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl(
return RC;
}
-comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const {
+static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod,
+ SmallVectorImpl<const NamedDecl *> &Redeclared) {
+ const DeclContext *DC = ObjCMethod->getDeclContext();
+ if (const ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(DC)) {
+ const ObjCInterfaceDecl *ID = IMD->getClassInterface();
+ if (!ID)
+ return;
+ // Add redeclared method here.
+ for (const ObjCCategoryDecl *ClsExtDecl = ID->getFirstClassExtension();
+ ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
+ if (ObjCMethodDecl *RedeclaredMethod =
+ ClsExtDecl->getMethod(ObjCMethod->getSelector(),
+ ObjCMethod->isInstanceMethod()))
+ Redeclared.push_back(RedeclaredMethod);
+ }
+ }
+}
+
+comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC,
+ const Decl *D) const {
+ comments::DeclInfo *ThisDeclInfo = new (*this) comments::DeclInfo;
+ ThisDeclInfo->CommentDecl = D;
+ ThisDeclInfo->IsFilled = false;
+ ThisDeclInfo->fill();
+ ThisDeclInfo->CommentDecl = FC->getDecl();
+ comments::FullComment *CFC =
+ new (*this) comments::FullComment(FC->getBlocks(),
+ ThisDeclInfo);
+ return CFC;
+
+}
+
+comments::FullComment *ASTContext::getCommentForDecl(
+ const Decl *D,
+ const Preprocessor *PP) const {
D = adjustDeclToTemplate(D);
+
const Decl *Canonical = D->getCanonicalDecl();
llvm::DenseMap<const Decl *, comments::FullComment *>::iterator Pos =
ParsedComments.find(Canonical);
- if (Pos != ParsedComments.end())
+
+ if (Pos != ParsedComments.end()) {
+ if (Canonical != D) {
+ comments::FullComment *FC = Pos->second;
+ comments::FullComment *CFC = cloneFullComment(FC, D);
+ return CFC;
+ }
return Pos->second;
-
+ }
+
const Decl *OriginalDecl;
+
const RawComment *RC = getRawCommentForAnyRedecl(D, &OriginalDecl);
- if (!RC)
+ if (!RC) {
+ if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
+ SmallVector<const NamedDecl*, 8> Overridden;
+ if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
+ addRedeclaredMethods(OMD, Overridden);
+ getOverriddenMethods(dyn_cast<NamedDecl>(D), Overridden);
+ for (unsigned i = 0, e = Overridden.size(); i < e; i++) {
+ if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) {
+ comments::FullComment *CFC = cloneFullComment(FC, D);
+ return CFC;
+ }
+ }
+ }
return NULL;
-
+ }
+
+ // If the RawComment was attached to other redeclaration of this Decl, we
+ // should parse the comment in context of that other Decl. This is important
+ // because comments can contain references to parameter names which can be
+ // different across redeclarations.
if (D != OriginalDecl)
- return getCommentForDecl(OriginalDecl);
+ return getCommentForDecl(OriginalDecl, PP);
- comments::FullComment *FC = RC->parse(*this, D);
+ comments::FullComment *FC = RC->parse(*this, PP, D);
ParsedComments[Canonical] = FC;
return FC;
}
@@ -481,6 +615,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
Int128Decl(0), UInt128Decl(0),
BuiltinVaListDecl(0),
ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0),
+ BOOLDecl(0),
CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0),
FILEDecl(0),
jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0),
@@ -495,6 +630,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
DeclarationNames(*this),
ExternalSource(0), Listener(0),
Comments(SM), CommentsLoaded(false),
+ CommentCommandTraits(BumpAlloc),
LastSDM(0, 0),
UniqueBlockByRefTypeID(0)
{
@@ -683,12 +819,12 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
InitBuiltinType(Int128Ty, BuiltinType::Int128);
InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128);
- if (LangOpts.CPlusPlus) { // C++ 3.9.1p5
+ if (LangOpts.CPlusPlus && LangOpts.WChar) { // C++ 3.9.1p5
if (TargetInfo::isTypeSigned(Target.getWCharType()))
InitBuiltinType(WCharTy, BuiltinType::WChar_S);
else // -fshort-wchar makes wchar_t be unsigned.
InitBuiltinType(WCharTy, BuiltinType::WChar_U);
- } else // C99
+ } else // C99 (or C++ using -fno-wchar)
WCharTy = getFromTargetType(Target.getWCharType());
WIntTy = getFromTargetType(Target.getWIntType());
@@ -725,6 +861,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
// Placeholder type for unbridged ARC casts.
InitBuiltinType(ARCUnbridgedCastTy, BuiltinType::ARCUnbridgedCast);
+ // Placeholder type for builtin functions.
+ InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn);
+
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
@@ -909,7 +1048,7 @@ bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD,
ASTContext::overridden_cxx_method_iterator
ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
- = OverriddenMethods.find(Method);
+ = OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
return 0;
@@ -919,7 +1058,7 @@ ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
ASTContext::overridden_cxx_method_iterator
ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
- = OverriddenMethods.find(Method);
+ = OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
return 0;
@@ -929,7 +1068,7 @@ ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {
unsigned
ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const {
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
- = OverriddenMethods.find(Method);
+ = OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
return 0;
@@ -938,9 +1077,30 @@ ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const {
void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
const CXXMethodDecl *Overridden) {
+ assert(Method->isCanonicalDecl() && Overridden->isCanonicalDecl());
OverriddenMethods[Method].push_back(Overridden);
}
+void ASTContext::getOverriddenMethods(
+ const NamedDecl *D,
+ SmallVectorImpl<const NamedDecl *> &Overridden) const {
+ assert(D);
+
+ if (const CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
+ Overridden.append(CXXMethod->begin_overridden_methods(),
+ CXXMethod->end_overridden_methods());
+ return;
+ }
+
+ const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
+ if (!Method)
+ return;
+
+ SmallVector<const ObjCMethodDecl *, 8> OverDecls;
+ Method->getOverriddenMethods(OverDecls);
+ Overridden.append(OverDecls.begin(), OverDecls.end());
+}
+
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
assert(!Import->NextLocalImport && "Import declaration already in the chain");
assert(!Import->isFromASTFile() && "Non-local import declaration");
@@ -1062,6 +1222,27 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
return toCharUnitsFromBits(Align);
}
+// getTypeInfoDataSizeInChars - Return the size of a type, in
+// chars. If the type is a record, its data size is returned. This is
+// the size of the memcpy that's performed when assigning this type
+// using a trivial copy/move assignment operator.
+std::pair<CharUnits, CharUnits>
+ASTContext::getTypeInfoDataSizeInChars(QualType T) const {
+ std::pair<CharUnits, CharUnits> sizeAndAlign = getTypeInfoInChars(T);
+
+ // In C++, objects can sometimes be allocated into the tail padding
+ // of a base-class subobject. We decide whether that's possible
+ // during class layout, so here we can just trust the layout results.
+ if (getLangOpts().CPlusPlus) {
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl());
+ sizeAndAlign.first = layout.getDataSize();
+ }
+ }
+
+ return sizeAndAlign;
+}
+
std::pair<CharUnits, CharUnits>
ASTContext::getTypeInfoInChars(const Type *T) const {
std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
@@ -3353,6 +3534,12 @@ QualType ASTContext::getPointerDiffType() const {
return getFromTargetType(Target->getPtrDiffType(0));
}
+/// \brief Return the unique type for "pid_t" defined in
+/// <sys/types.h>. We need this to compute the correct type for vfork().
+QualType ASTContext::getProcessIDType() const {
+ return getFromTargetType(Target->getProcessIDType());
+}
+
//===----------------------------------------------------------------------===//
// Type Operators
//===----------------------------------------------------------------------===//
@@ -3581,11 +3768,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
return Arg;
case TemplateArgument::Declaration: {
- if (Decl *D = Arg.getAsDecl())
- return TemplateArgument(D->getCanonicalDecl());
- return TemplateArgument((Decl*)0);
+ ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
+ return TemplateArgument(D, Arg.isDeclForReferenceParam());
}
+ case TemplateArgument::NullPtr:
+ return TemplateArgument(getCanonicalType(Arg.getNullPtrType()),
+ /*isNullPtr*/true);
+
case TemplateArgument::Template:
return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
@@ -4297,7 +4487,13 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
QualType BlockTy =
Expr->getType()->getAs<BlockPointerType>()->getPointeeType();
// Encode result type.
- getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), S);
+ if (getLangOpts().EncodeExtendedBlockSig)
+ getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None,
+ BlockTy->getAs<FunctionType>()->getResultType(),
+ S, true /*Extended*/);
+ else
+ getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(),
+ S);
// Compute size of all parameters.
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
@@ -4332,7 +4528,11 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
PType = PVDecl->getType();
} else if (PType->isFunctionType())
PType = PVDecl->getType();
- getObjCEncodingForType(PType, S);
+ if (getLangOpts().EncodeExtendedBlockSig)
+ getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, PType,
+ S, true /*Extended*/);
+ else
+ getObjCEncodingForType(PType, S);
S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
@@ -5393,6 +5593,65 @@ static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) {
return VaListTypedefDecl;
}
+static TypedefDecl *
+CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) {
+ RecordDecl *VaListDecl;
+ if (Context->getLangOpts().CPlusPlus) {
+ // namespace std { struct __va_list {
+ NamespaceDecl *NS;
+ NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
+ Context->getTranslationUnitDecl(),
+ /*Inline*/false, SourceLocation(),
+ SourceLocation(), &Context->Idents.get("std"),
+ /*PrevDecl*/0);
+
+ VaListDecl = CXXRecordDecl::Create(*Context, TTK_Struct,
+ Context->getTranslationUnitDecl(),
+ SourceLocation(), SourceLocation(),
+ &Context->Idents.get("__va_list"));
+
+ VaListDecl->setDeclContext(NS);
+
+ } else {
+ // struct __va_list {
+ VaListDecl = CreateRecordDecl(*Context, TTK_Struct,
+ Context->getTranslationUnitDecl(),
+ &Context->Idents.get("__va_list"));
+ }
+
+ VaListDecl->startDefinition();
+
+ // void * __ap;
+ FieldDecl *Field = FieldDecl::Create(const_cast<ASTContext &>(*Context),
+ VaListDecl,
+ SourceLocation(),
+ SourceLocation(),
+ &Context->Idents.get("__ap"),
+ Context->getPointerType(Context->VoidTy),
+ /*TInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false,
+ ICIS_NoInit);
+ Field->setAccess(AS_public);
+ VaListDecl->addDecl(Field);
+
+ // };
+ VaListDecl->completeDefinition();
+
+ // typedef struct __va_list __builtin_va_list;
+ TypeSourceInfo *TInfo
+ = Context->getTrivialTypeSourceInfo(Context->getRecordType(VaListDecl));
+
+ TypedefDecl *VaListTypeDecl
+ = TypedefDecl::Create(const_cast<ASTContext &>(*Context),
+ Context->getTranslationUnitDecl(),
+ SourceLocation(), SourceLocation(),
+ &Context->Idents.get("__builtin_va_list"),
+ TInfo);
+
+ return VaListTypeDecl;
+}
+
static TypedefDecl *CreateVaListDecl(const ASTContext *Context,
TargetInfo::BuiltinVaListKind Kind) {
switch (Kind) {
@@ -5406,6 +5665,8 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context,
return CreateX86_64ABIBuiltinVaListDecl(Context);
case TargetInfo::PNaClABIBuiltinVaList:
return CreatePNaClABIBuiltinVaListDecl(Context);
+ case TargetInfo::AAPCSABIBuiltinVaList:
+ return CreateAAPCSABIBuiltinVaListDecl(Context);
}
llvm_unreachable("Unhandled __builtin_va_list type kind");
@@ -5702,7 +5963,7 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
return false;
}
-/// QualifiedIdConformsQualifiedId - compare id<p,...> with id<p1,...>
+/// QualifiedIdConformsQualifiedId - compare id<pr,...> with id<pr1,...>
/// return true if lhs's protocols conform to rhs's protocol; false
/// otherwise.
bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
@@ -5711,8 +5972,8 @@ bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
return false;
}
-/// ObjCQualifiedClassTypesAreCompatible - compare Class<p,...> and
-/// Class<p1, ...>.
+/// ObjCQualifiedClassTypesAreCompatible - compare Class<pr,...> and
+/// Class<pr1, ...>.
bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
QualType rhs) {
const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>();
@@ -6315,10 +6576,13 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
for (unsigned i = 0; i < proto_nargs; ++i) {
QualType argTy = proto->getArgType(i);
- // Look at the promotion type of enum types, since that is the type used
+ // Look at the converted type of enum types, since that is the type used
// to pass enum values.
- if (const EnumType *Enum = argTy->getAs<EnumType>())
- argTy = Enum->getDecl()->getPromotionType();
+ if (const EnumType *Enum = argTy->getAs<EnumType>()) {
+ argTy = Enum->getDecl()->getIntegerType();
+ if (argTy.isNull())
+ return QualType();
+ }
if (argTy->isPromotableIntegerType() ||
getCanonicalType(argTy).getUnqualifiedType() == FloatTy)
@@ -6725,7 +6989,7 @@ unsigned ASTContext::getIntWidth(QualType T) const {
return (unsigned)getTypeSize(T);
}
-QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
+QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
assert(T->hasSignedIntegerRepresentation() && "Unexpected type");
// Turn <4 x signed int> -> <4 x unsigned int>
@@ -6959,6 +7223,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
return QualType();
}
break;
+ case 'p':
+ Type = Context.getProcessIDType();
+ break;
}
// If there are modifiers and if we're allowed to parse them, go for it.
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index a605f1a..0b9c524 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -430,6 +430,15 @@ class TemplateDiff {
/// arguments or the type arguments that are templates.
TemplateDecl *FromTD, *ToTD;
+ /// FromQual, ToQual - Qualifiers for template types.
+ Qualifiers FromQual, ToQual;
+
+ /// FromInt, ToInt - APSInt's for integral arguments.
+ llvm::APSInt FromInt, ToInt;
+
+ /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid.
+ bool IsValidFromInt, IsValidToInt;
+
/// FromDefault, ToDefault - Whether the argument is a default argument.
bool FromDefault, ToDefault;
@@ -480,6 +489,21 @@ class TemplateDiff {
FlatTree[CurrentNode].ToExpr = ToExpr;
}
+ /// SetNode - Set FromInt and ToInt of the current node.
+ void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt,
+ bool IsValidFromInt, bool IsValidToInt) {
+ FlatTree[CurrentNode].FromInt = FromInt;
+ FlatTree[CurrentNode].ToInt = ToInt;
+ FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt;
+ FlatTree[CurrentNode].IsValidToInt = IsValidToInt;
+ }
+
+ /// SetNode - Set FromQual and ToQual of the current node.
+ void SetNode(Qualifiers FromQual, Qualifiers ToQual) {
+ FlatTree[CurrentNode].FromQual = FromQual;
+ FlatTree[CurrentNode].ToQual = ToQual;
+ }
+
/// SetSame - Sets the same flag of the current node.
void SetSame(bool Same) {
FlatTree[CurrentNode].Same = Same;
@@ -557,6 +581,12 @@ class TemplateDiff {
(FlatTree[ReadNode].FromTD || FlatTree[ReadNode].ToTD);
}
+ /// NodeIsAPSInt - Returns true if the arugments are stored in APSInt's.
+ bool NodeIsAPSInt() {
+ return FlatTree[ReadNode].IsValidFromInt ||
+ FlatTree[ReadNode].IsValidToInt;
+ }
+
/// GetNode - Gets the FromType and ToType.
void GetNode(QualType &FromType, QualType &ToType) {
FromType = FlatTree[ReadNode].FromType;
@@ -575,6 +605,21 @@ class TemplateDiff {
ToTD = FlatTree[ReadNode].ToTD;
}
+ /// GetNode - Gets the FromInt and ToInt.
+ void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
+ bool &IsValidFromInt, bool &IsValidToInt) {
+ FromInt = FlatTree[ReadNode].FromInt;
+ ToInt = FlatTree[ReadNode].ToInt;
+ IsValidFromInt = FlatTree[ReadNode].IsValidFromInt;
+ IsValidToInt = FlatTree[ReadNode].IsValidToInt;
+ }
+
+ /// GetNode - Gets the FromQual and ToQual.
+ void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) {
+ FromQual = FlatTree[ReadNode].FromQual;
+ ToQual = FlatTree[ReadNode].ToQual;
+ }
+
/// NodeIsSame - Returns true the arguments are the same.
bool NodeIsSame() {
return FlatTree[ReadNode].Same;
@@ -778,18 +823,21 @@ class TemplateDiff {
if (Context.hasSameType(FromType, ToType)) {
Tree.SetSame(true);
} else {
+ Qualifiers FromQual = FromType.getQualifiers(),
+ ToQual = ToType.getQualifiers();
const TemplateSpecializationType *FromArgTST =
GetTemplateSpecializationType(Context, FromType);
const TemplateSpecializationType *ToArgTST =
GetTemplateSpecializationType(Context, ToType);
- if (FromArgTST && ToArgTST) {
- bool SameTemplate = hasSameTemplate(FromArgTST, ToArgTST);
- if (SameTemplate) {
- Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),
- ToArgTST->getTemplateName().getAsTemplateDecl());
- DiffTemplate(FromArgTST, ToArgTST);
- }
+ if (FromArgTST && ToArgTST &&
+ hasSameTemplate(FromArgTST, ToArgTST)) {
+ FromQual -= QualType(FromArgTST, 0).getQualifiers();
+ ToQual -= QualType(ToArgTST, 0).getQualifiers();
+ Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),
+ ToArgTST->getTemplateName().getAsTemplateDecl());
+ Tree.SetNode(FromQual, ToQual);
+ DiffTemplate(FromArgTST, ToArgTST);
}
}
}
@@ -799,12 +847,41 @@ class TemplateDiff {
if (NonTypeTemplateParmDecl *DefaultNTTPD =
dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {
Expr *FromExpr, *ToExpr;
- GetExpr(FromIter, DefaultNTTPD, FromExpr);
- GetExpr(ToIter, DefaultNTTPD, ToExpr);
- Tree.SetNode(FromExpr, ToExpr);
- Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
- Tree.SetDefault(FromIter.isEnd() && FromExpr,
- ToIter.isEnd() && ToExpr);
+ llvm::APSInt FromInt, ToInt;
+ bool HasFromInt = !FromIter.isEnd() &&
+ FromIter->getKind() == TemplateArgument::Integral;
+ bool HasToInt = !ToIter.isEnd() &&
+ ToIter->getKind() == TemplateArgument::Integral;
+ //bool IsValidFromInt = false, IsValidToInt = false;
+ if (HasFromInt)
+ FromInt = FromIter->getAsIntegral();
+ else
+ GetExpr(FromIter, DefaultNTTPD, FromExpr);
+
+ if (HasToInt)
+ ToInt = ToIter->getAsIntegral();
+ else
+ GetExpr(ToIter, DefaultNTTPD, ToExpr);
+
+ if (!HasFromInt && !HasToInt) {
+ Tree.SetNode(FromExpr, ToExpr);
+ Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
+ Tree.SetDefault(FromIter.isEnd() && FromExpr,
+ ToIter.isEnd() && ToExpr);
+ } else {
+ if (!HasFromInt && FromExpr) {
+ FromInt = FromExpr->EvaluateKnownConstInt(Context);
+ HasFromInt = true;
+ }
+ if (!HasToInt && ToExpr) {
+ ToInt = ToExpr->EvaluateKnownConstInt(Context);
+ HasToInt = true;
+ }
+ Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
+ Tree.SetSame(llvm::APSInt::isSameValue(FromInt, ToInt));
+ Tree.SetDefault(FromIter.isEnd() && HasFromInt,
+ ToIter.isEnd() && HasToInt);
+ }
}
// Handle Templates
@@ -824,6 +901,26 @@ class TemplateDiff {
}
}
+ /// makeTemplateList - Dump every template alias into the vector.
+ static void makeTemplateList(
+ SmallVector<const TemplateSpecializationType*, 1> &TemplateList,
+ const TemplateSpecializationType *TST) {
+ while (TST) {
+ TemplateList.push_back(TST);
+ if (!TST->isTypeAlias())
+ return;
+ TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
+ }
+ }
+
+ /// hasSameBaseTemplate - Returns true when the base templates are the same,
+ /// even if the template arguments are not.
+ static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST,
+ const TemplateSpecializationType *ToTST) {
+ return FromTST->getTemplateName().getAsTemplateDecl()->getIdentifier() ==
+ ToTST->getTemplateName().getAsTemplateDecl()->getIdentifier();
+ }
+
/// hasSameTemplate - Returns true if both types are specialized from the
/// same template declaration. If they come from different template aliases,
/// do a parallel ascension search to determine the highest template alias in
@@ -831,49 +928,29 @@ class TemplateDiff {
static bool hasSameTemplate(const TemplateSpecializationType *&FromTST,
const TemplateSpecializationType *&ToTST) {
// Check the top templates if they are the same.
- if (FromTST->getTemplateName().getAsTemplateDecl()->getIdentifier() ==
- ToTST->getTemplateName().getAsTemplateDecl()->getIdentifier())
+ if (hasSameBaseTemplate(FromTST, ToTST))
return true;
// Create vectors of template aliases.
SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,
ToTemplateList;
- const TemplateSpecializationType *TempToTST = ToTST, *TempFromTST = FromTST;
- FromTemplateList.push_back(FromTST);
- ToTemplateList.push_back(ToTST);
-
- // Dump every template alias into the vectors.
- while (TempFromTST->isTypeAlias()) {
- TempFromTST =
- TempFromTST->getAliasedType()->getAs<TemplateSpecializationType>();
- if (!TempFromTST)
- break;
- FromTemplateList.push_back(TempFromTST);
- }
- while (TempToTST->isTypeAlias()) {
- TempToTST =
- TempToTST->getAliasedType()->getAs<TemplateSpecializationType>();
- if (!TempToTST)
- break;
- ToTemplateList.push_back(TempToTST);
- }
+ makeTemplateList(FromTemplateList, FromTST);
+ makeTemplateList(ToTemplateList, ToTST);
SmallVector<const TemplateSpecializationType*, 1>::reverse_iterator
FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),
ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();
// Check if the lowest template types are the same. If not, return.
- if ((*FromIter)->getTemplateName().getAsTemplateDecl()->getIdentifier() !=
- (*ToIter)->getTemplateName().getAsTemplateDecl()->getIdentifier())
+ if (!hasSameBaseTemplate(*FromIter, *ToIter))
return false;
// Begin searching up the template aliases. The bottom most template
// matches so move up until one pair does not match. Use the template
// right before that one.
for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {
- if ((*FromIter)->getTemplateName().getAsTemplateDecl()->getIdentifier() !=
- (*ToIter)->getTemplateName().getAsTemplateDecl()->getIdentifier())
+ if (!hasSameBaseTemplate(*FromIter, *ToIter))
break;
}
@@ -923,7 +1000,9 @@ class TemplateDiff {
bool isVariadic = DefaultTTPD->isParameterPack();
TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument();
- TemplateDecl *DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
+ TemplateDecl *DefaultTD = 0;
+ if (TA.getKind() != TemplateArgument::Null)
+ DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
if (!Iter.isEnd())
ArgDecl = Iter->getAsTemplate().getAsTemplateDecl();
@@ -1018,6 +1097,15 @@ class TemplateDiff {
Tree.ToDefault(), Tree.NodeIsSame());
return;
}
+
+ if (Tree.NodeIsAPSInt()) {
+ llvm::APSInt FromInt, ToInt;
+ bool IsValidFromInt, IsValidToInt;
+ Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt);
+ PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt,
+ Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
+ return;
+ }
llvm_unreachable("Unable to deduce template difference.");
}
@@ -1027,6 +1115,10 @@ class TemplateDiff {
assert(Tree.HasChildren() && "Template difference not found in diff tree.");
+ Qualifiers FromQual, ToQual;
+ Tree.GetNode(FromQual, ToQual);
+ PrintQualifiers(FromQual, ToQual);
+
OS << FromTD->getNameAsString() << '<';
Tree.MoveToChild();
unsigned NumElideArgs = 0;
@@ -1088,6 +1180,17 @@ class TemplateDiff {
return;
}
+ if (!FromType.isNull() && !ToType.isNull() &&
+ FromType.getLocalUnqualifiedType() ==
+ ToType.getLocalUnqualifiedType()) {
+ Qualifiers FromQual = FromType.getLocalQualifiers(),
+ ToQual = ToType.getLocalQualifiers(),
+ CommonQual;
+ PrintQualifiers(FromQual, ToQual);
+ FromType.getLocalUnqualifiedType().print(OS, Policy);
+ return;
+ }
+
std::string FromTypeStr = FromType.isNull() ? "(no argument)"
: FromType.getAsString();
std::string ToTypeStr = ToType.isNull() ? "(no argument)"
@@ -1177,6 +1280,34 @@ class TemplateDiff {
}
}
+ /// PrintAPSInt - Handles printing of integral arguments, highlighting
+ /// argument differences.
+ void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt,
+ bool IsValidFromInt, bool IsValidToInt, bool FromDefault,
+ bool ToDefault, bool Same) {
+ assert((IsValidFromInt || IsValidToInt) &&
+ "Only one integral argument may be missing.");
+
+ if (Same) {
+ OS << FromInt.toString(10);
+ } else if (!PrintTree) {
+ OS << (FromDefault ? "(default) " : "");
+ Bold();
+ OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)");
+ Unbold();
+ } else {
+ OS << (FromDefault ? "[(default) " : "[");
+ Bold();
+ OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)");
+ Unbold();
+ OS << " != " << (ToDefault ? "(default) " : "");
+ Bold();
+ OS << (IsValidToInt ? ToInt.toString(10) : "(no argument)");
+ Unbold();
+ OS << ']';
+ }
+ }
+
// Prints the appropriate placeholder for elided template arguments.
void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
if (PrintTree) {
@@ -1191,6 +1322,68 @@ class TemplateDiff {
OS << "[" << NumElideArgs << " * ...]";
}
+ // Prints and highlights differences in Qualifiers.
+ void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {
+ // Both types have no qualifiers
+ if (FromQual.empty() && ToQual.empty())
+ return;
+
+ // Both types have same qualifiers
+ if (FromQual == ToQual) {
+ PrintQualifier(FromQual, /*ApplyBold*/false);
+ return;
+ }
+
+ // Find common qualifiers and strip them from FromQual and ToQual.
+ Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual,
+ ToQual);
+
+ // The qualifiers are printed before the template name.
+ // Inline printing:
+ // The common qualifiers are printed. Then, qualifiers only in this type
+ // are printed and highlighted. Finally, qualifiers only in the other
+ // type are printed and highlighted inside parentheses after "missing".
+ // Tree printing:
+ // Qualifiers are printed next to each other, inside brackets, and
+ // separated by "!=". The printing order is:
+ // common qualifiers, highlighted from qualifiers, "!=",
+ // common qualifiers, highlighted to qualifiers
+ if (PrintTree) {
+ OS << "[";
+ if (CommonQual.empty() && FromQual.empty()) {
+ Bold();
+ OS << "(no qualifiers) ";
+ Unbold();
+ } else {
+ PrintQualifier(CommonQual, /*ApplyBold*/false);
+ PrintQualifier(FromQual, /*ApplyBold*/true);
+ }
+ OS << "!= ";
+ if (CommonQual.empty() && ToQual.empty()) {
+ Bold();
+ OS << "(no qualifiers)";
+ Unbold();
+ } else {
+ PrintQualifier(CommonQual, /*ApplyBold*/false,
+ /*appendSpaceIfNonEmpty*/!ToQual.empty());
+ PrintQualifier(ToQual, /*ApplyBold*/true,
+ /*appendSpaceIfNonEmpty*/false);
+ }
+ OS << "] ";
+ } else {
+ PrintQualifier(CommonQual, /*ApplyBold*/false);
+ PrintQualifier(FromQual, /*ApplyBold*/true);
+ }
+ }
+
+ void PrintQualifier(Qualifiers Q, bool ApplyBold,
+ bool AppendSpaceIfNonEmpty = true) {
+ if (Q.empty()) return;
+ if (ApplyBold) Bold();
+ Q.print(OS, Policy, AppendSpaceIfNonEmpty);
+ if (ApplyBold) Unbold();
+ }
+
public:
TemplateDiff(ASTContext &Context, QualType FromType, QualType ToType,
@@ -1210,6 +1403,9 @@ public:
/// DiffTemplate - Start the template type diffing.
void DiffTemplate() {
+ Qualifiers FromQual = FromType.getQualifiers(),
+ ToQual = ToType.getQualifiers();
+
const TemplateSpecializationType *FromOrigTST =
GetTemplateSpecializationType(Context, FromType);
const TemplateSpecializationType *ToOrigTST =
@@ -1224,7 +1420,10 @@ public:
return;
}
+ FromQual -= QualType(FromOrigTST, 0).getQualifiers();
+ ToQual -= QualType(ToOrigTST, 0).getQualifiers();
Tree.SetNode(FromType, ToType);
+ Tree.SetNode(FromQual, ToQual);
// Same base template, but different arguments.
Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(),
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 3e952ac..0d4f303 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -228,16 +228,12 @@ namespace {
public:
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) {
- if (!Complain)
- return DiagnosticBuilder::getEmpty();
-
+ assert(Complain && "Not allowed to complain");
return C1.getDiagnostics().Report(Loc, DiagID);
}
DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) {
- if (!Complain)
- return DiagnosticBuilder::getEmpty();
-
+ assert(Complain && "Not allowed to complain");
return C2.getDiagnostics().Report(Loc, DiagID);
}
};
@@ -288,7 +284,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case TemplateArgument::Type:
return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType());
-
+
case TemplateArgument::Integral:
if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(),
Arg2.getIntegralType()))
@@ -297,10 +293,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return llvm::APSInt::isSameValue(Arg1.getAsIntegral(), Arg2.getAsIntegral());
case TemplateArgument::Declaration:
- if (!Arg1.getAsDecl() || !Arg2.getAsDecl())
- return !Arg1.getAsDecl() && !Arg2.getAsDecl();
return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl());
-
+
+ case TemplateArgument::NullPtr:
+ return true; // FIXME: Is this correct?
+
case TemplateArgument::Template:
return IsStructurallyEquivalent(Context,
Arg1.getAsTemplate(),
@@ -822,33 +819,47 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
FieldDecl *Field1, FieldDecl *Field2) {
RecordDecl *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
-
- if (!IsStructurallyEquivalent(Context,
+
+ // For anonymous structs/unions, match up the anonymous struct/union type
+ // declarations directly, so that we don't go off searching for anonymous
+ // types
+ if (Field1->isAnonymousStructOrUnion() &&
+ Field2->isAnonymousStructOrUnion()) {
+ RecordDecl *D1 = Field1->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *D2 = Field2->getType()->castAs<RecordType>()->getDecl();
+ return IsStructurallyEquivalent(Context, D1, D2);
+ }
+
+ if (!IsStructurallyEquivalent(Context,
Field1->getType(), Field2->getType())) {
- Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(Owner2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_field)
- << Field2->getDeclName() << Field2->getType();
- Context.Diag1(Field1->getLocation(), diag::note_odr_field)
- << Field1->getDeclName() << Field1->getType();
+ if (Context.Complain) {
+ Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(Owner2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_field)
+ << Field2->getDeclName() << Field2->getType();
+ Context.Diag1(Field1->getLocation(), diag::note_odr_field)
+ << Field1->getDeclName() << Field1->getType();
+ }
return false;
}
if (Field1->isBitField() != Field2->isBitField()) {
- Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(Owner2);
- if (Field1->isBitField()) {
- Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
- << Field1->getDeclName() << Field1->getType()
- << Field1->getBitWidthValue(Context.C1);
- Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field)
- << Field2->getDeclName();
- } else {
- Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
- << Field2->getDeclName() << Field2->getType()
- << Field2->getBitWidthValue(Context.C2);
- Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field)
- << Field1->getDeclName();
+ if (Context.Complain) {
+ Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(Owner2);
+ if (Field1->isBitField()) {
+ Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
+ << Field1->getDeclName() << Field1->getType()
+ << Field1->getBitWidthValue(Context.C1);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field)
+ << Field2->getDeclName();
+ } else {
+ Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
+ << Field2->getDeclName() << Field2->getType()
+ << Field2->getBitWidthValue(Context.C2);
+ Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field)
+ << Field1->getDeclName();
+ }
}
return false;
}
@@ -859,12 +870,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
unsigned Bits2 = Field2->getBitWidthValue(Context.C2);
if (Bits1 != Bits2) {
- Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(Owner2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
- << Field2->getDeclName() << Field2->getType() << Bits2;
- Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
- << Field1->getDeclName() << Field1->getType() << Bits1;
+ if (Context.Complain) {
+ Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(Owner2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
+ << Field2->getDeclName() << Field2->getType() << Bits2;
+ Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
+ << Field1->getDeclName() << Field1->getType() << Bits1;
+ }
return false;
}
}
@@ -872,17 +885,65 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return true;
}
+/// \brief Find the index of the given anonymous struct/union within its
+/// context.
+///
+/// \returns Returns the index of this anonymous struct/union in its context,
+/// including the next assigned index (if none of them match). Returns an
+/// empty option if the context is not a record, i.e.. if the anonymous
+/// struct/union is at namespace or block scope.
+static llvm::Optional<unsigned>
+findAnonymousStructOrUnionIndex(RecordDecl *Anon) {
+ ASTContext &Context = Anon->getASTContext();
+ QualType AnonTy = Context.getRecordType(Anon);
+
+ RecordDecl *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
+ if (!Owner)
+ return llvm::Optional<unsigned>();
+
+ unsigned Index = 0;
+ for (DeclContext::decl_iterator D = Owner->noload_decls_begin(),
+ DEnd = Owner->noload_decls_end();
+ D != DEnd; ++D) {
+ FieldDecl *F = dyn_cast<FieldDecl>(*D);
+ if (!F || !F->isAnonymousStructOrUnion())
+ continue;
+
+ if (Context.hasSameType(F->getType(), AnonTy))
+ break;
+
+ ++Index;
+ }
+
+ return Index;
+}
+
/// \brief Determine structural equivalence of two records.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
RecordDecl *D1, RecordDecl *D2) {
if (D1->isUnion() != D2->isUnion()) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
- << D1->getDeclName() << (unsigned)D1->getTagKind();
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
+ << D1->getDeclName() << (unsigned)D1->getTagKind();
+ }
return false;
}
-
+
+ if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) {
+ // If both anonymous structs/unions are in a record context, make sure
+ // they occur in the same location in the context records.
+ if (llvm::Optional<unsigned> Index1
+ = findAnonymousStructOrUnionIndex(D1)) {
+ if (llvm::Optional<unsigned> Index2
+ = findAnonymousStructOrUnionIndex(D2)) {
+ if (*Index1 != *Index2)
+ return false;
+ }
+ }
+ }
+
// If both declarations are class template specializations, we know
// the ODR applies, so check the template and template arguments.
ClassTemplateSpecializationDecl *Spec1
@@ -920,12 +981,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
if (CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
- << D2CXX->getNumBases();
- Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
- << D1CXX->getNumBases();
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
+ << D2CXX->getNumBases();
+ Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
+ << D1CXX->getNumBases();
+ }
return false;
}
@@ -937,38 +1000,44 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
++Base1, ++Base2) {
if (!IsStructurallyEquivalent(Context,
Base1->getType(), Base2->getType())) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(Base2->getLocStart(), diag::note_odr_base)
- << Base2->getType()
- << Base2->getSourceRange();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
- << Base1->getType()
- << Base1->getSourceRange();
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(Base2->getLocStart(), diag::note_odr_base)
+ << Base2->getType()
+ << Base2->getSourceRange();
+ Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
+ << Base1->getType()
+ << Base1->getSourceRange();
+ }
return false;
}
// Check virtual vs. non-virtual inheritance mismatch.
if (Base1->isVirtual() != Base2->isVirtual()) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(Base2->getLocStart(),
- diag::note_odr_virtual_base)
- << Base2->isVirtual() << Base2->getSourceRange();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
- << Base1->isVirtual()
- << Base1->getSourceRange();
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(Base2->getLocStart(),
+ diag::note_odr_virtual_base)
+ << Base2->isVirtual() << Base2->getSourceRange();
+ Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
+ << Base1->isVirtual()
+ << Base1->getSourceRange();
+ }
return false;
}
}
} else if (D1CXX->getNumBases() > 0) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
- << Base1->getType()
- << Base1->getSourceRange();
- Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
+ Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
+ << Base1->getType()
+ << Base1->getSourceRange();
+ Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
+ }
return false;
}
}
@@ -981,11 +1050,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Field1 != Field1End;
++Field1, ++Field2) {
if (Field2 == Field2End) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag1(Field1->getLocation(), diag::note_odr_field)
- << Field1->getDeclName() << Field1->getType();
- Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag1(Field1->getLocation(), diag::note_odr_field)
+ << Field1->getDeclName() << Field1->getType();
+ Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
+ }
return false;
}
@@ -994,11 +1065,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
if (Field2 != Field2End) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_field)
- << Field2->getDeclName() << Field2->getType();
- Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_field)
+ << Field2->getDeclName() << Field2->getType();
+ Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
+ }
return false;
}
@@ -1014,12 +1087,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
EC1End = D1->enumerator_end();
EC1 != EC1End; ++EC1, ++EC2) {
if (EC2 == EC2End) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
- << EC1->getDeclName()
- << EC1->getInitVal().toString(10);
- Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
+ << EC1->getDeclName()
+ << EC1->getInitVal().toString(10);
+ Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
+ }
return false;
}
@@ -1027,25 +1102,29 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
llvm::APSInt Val2 = EC2->getInitVal();
if (!llvm::APSInt::isSameValue(Val1, Val2) ||
!IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) {
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
+ << EC2->getDeclName()
+ << EC2->getInitVal().toString(10);
+ Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
+ << EC1->getDeclName()
+ << EC1->getInitVal().toString(10);
+ }
+ return false;
+ }
+ }
+
+ if (EC2 != EC2End) {
+ if (Context.Complain) {
Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
<< Context.C2.getTypeDeclType(D2);
Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
<< EC2->getDeclName()
<< EC2->getInitVal().toString(10);
- Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
- << EC1->getDeclName()
- << EC1->getInitVal().toString(10);
- return false;
+ Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
}
- }
-
- if (EC2 != EC2End) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
- << EC2->getDeclName()
- << EC2->getInitVal().toString(10);
- Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
return false;
}
@@ -1056,20 +1135,24 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
TemplateParameterList *Params1,
TemplateParameterList *Params2) {
if (Params1->size() != Params2->size()) {
- Context.Diag2(Params2->getTemplateLoc(),
- diag::err_odr_different_num_template_parameters)
- << Params1->size() << Params2->size();
- Context.Diag1(Params1->getTemplateLoc(),
- diag::note_odr_template_parameter_list);
+ if (Context.Complain) {
+ Context.Diag2(Params2->getTemplateLoc(),
+ diag::err_odr_different_num_template_parameters)
+ << Params1->size() << Params2->size();
+ Context.Diag1(Params1->getTemplateLoc(),
+ diag::note_odr_template_parameter_list);
+ }
return false;
}
for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) {
- Context.Diag2(Params2->getParam(I)->getLocation(),
- diag::err_odr_different_template_parameter_kind);
- Context.Diag1(Params1->getParam(I)->getLocation(),
- diag::note_odr_template_parameter_here);
+ if (Context.Complain) {
+ Context.Diag2(Params2->getParam(I)->getLocation(),
+ diag::err_odr_different_template_parameter_kind);
+ Context.Diag1(Params1->getParam(I)->getLocation(),
+ diag::note_odr_template_parameter_here);
+ }
return false;
}
@@ -1087,10 +1170,12 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
TemplateTypeParmDecl *D1,
TemplateTypeParmDecl *D2) {
if (D1->isParameterPack() != D2->isParameterPack()) {
- Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
- << D2->isParameterPack();
- Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
- << D1->isParameterPack();
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
+ << D2->isParameterPack();
+ Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
+ << D1->isParameterPack();
+ }
return false;
}
@@ -1100,24 +1185,25 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
NonTypeTemplateParmDecl *D1,
NonTypeTemplateParmDecl *D2) {
- // FIXME: Enable once we have variadic templates.
-#if 0
if (D1->isParameterPack() != D2->isParameterPack()) {
- Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
- << D2->isParameterPack();
- Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
- << D1->isParameterPack();
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
+ << D2->isParameterPack();
+ Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
+ << D1->isParameterPack();
+ }
return false;
}
-#endif
// Check types.
if (!Context.IsStructurallyEquivalent(D1->getType(), D2->getType())) {
- Context.Diag2(D2->getLocation(),
- diag::err_odr_non_type_parameter_type_inconsistent)
- << D2->getType() << D1->getType();
- Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
- << D1->getType();
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(),
+ diag::err_odr_non_type_parameter_type_inconsistent)
+ << D2->getType() << D1->getType();
+ Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
+ << D1->getType();
+ }
return false;
}
@@ -1127,17 +1213,16 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
TemplateTemplateParmDecl *D1,
TemplateTemplateParmDecl *D2) {
- // FIXME: Enable once we have variadic templates.
-#if 0
if (D1->isParameterPack() != D2->isParameterPack()) {
- Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
- << D2->isParameterPack();
- Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
- << D1->isParameterPack();
+ if (Context.Complain) {
+ Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack)
+ << D2->isParameterPack();
+ Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
+ << D1->isParameterPack();
+ }
return false;
}
-#endif
-
+
// Check template parameter lists.
return IsStructurallyEquivalent(Context, D1->getTemplateParameters(),
D2->getTemplateParameters());
@@ -1509,11 +1594,26 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
ExceptionTypes.push_back(ExceptionType);
}
- FunctionProtoType::ExtProtoInfo EPI = T->getExtProtoInfo();
- EPI.Exceptions = ExceptionTypes.data();
-
+ FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo();
+ FunctionProtoType::ExtProtoInfo ToEPI;
+
+ ToEPI.ExtInfo = FromEPI.ExtInfo;
+ ToEPI.Variadic = FromEPI.Variadic;
+ ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn;
+ ToEPI.TypeQuals = FromEPI.TypeQuals;
+ ToEPI.RefQualifier = FromEPI.RefQualifier;
+ ToEPI.NumExceptions = ExceptionTypes.size();
+ ToEPI.Exceptions = ExceptionTypes.data();
+ ToEPI.ConsumedArguments = FromEPI.ConsumedArguments;
+ ToEPI.ExceptionSpecType = FromEPI.ExceptionSpecType;
+ ToEPI.NoexceptExpr = Importer.Import(FromEPI.NoexceptExpr);
+ ToEPI.ExceptionSpecDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(FromEPI.ExceptionSpecDecl));
+ ToEPI.ExceptionSpecTemplate = cast_or_null<FunctionDecl>(
+ Importer.Import(FromEPI.ExceptionSpecTemplate));
+
return Importer.getToContext().getFunctionType(ToResultType, ArgTypes.data(),
- ArgTypes.size(), EPI);
+ ArgTypes.size(), ToEPI);
}
QualType ASTNodeImporter::VisitParenType(const ParenType *T) {
@@ -1961,11 +2061,20 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
return TemplateArgument(From, ToType);
}
- case TemplateArgument::Declaration:
- if (Decl *To = Importer.Import(From.getAsDecl()))
- return TemplateArgument(To);
+ case TemplateArgument::Declaration: {
+ ValueDecl *FromD = From.getAsDecl();
+ if (ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(FromD)))
+ return TemplateArgument(To, From.isDeclForReferenceParam());
return TemplateArgument();
-
+ }
+
+ case TemplateArgument::NullPtr: {
+ QualType ToType = Importer.Import(From.getNullPtrType());
+ if (ToType.isNull())
+ return TemplateArgument();
+ return TemplateArgument(ToType, /*isNullPtr*/true);
+ }
+
case TemplateArgument::Template: {
TemplateName ToTemplate = Importer.Import(From.getAsTemplate());
if (ToTemplate.isNull())
@@ -2318,6 +2427,20 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
}
if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
+ if (D->isAnonymousStructOrUnion() &&
+ FoundRecord->isAnonymousStructOrUnion()) {
+ // If both anonymous structs/unions are in a record context, make sure
+ // they occur in the same location in the context records.
+ if (llvm::Optional<unsigned> Index1
+ = findAnonymousStructOrUnionIndex(D)) {
+ if (llvm::Optional<unsigned> Index2
+ = findAnonymousStructOrUnionIndex(FoundRecord)) {
+ if (*Index1 != *Index2)
+ continue;
+ }
+ }
+ }
+
if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
if ((SearchName && !D->isCompleteDefinition())
|| (D->isCompleteDefinition() &&
@@ -2491,8 +2614,30 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Import additional name location/type info.
ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+ QualType FromTy = D->getType();
+ bool usedDifferentExceptionSpec = false;
+
+ if (const FunctionProtoType *
+ FromFPT = D->getType()->getAs<FunctionProtoType>()) {
+ FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();
+ // FunctionProtoType::ExtProtoInfo's ExceptionSpecDecl can point to the
+ // FunctionDecl that we are importing the FunctionProtoType for.
+ // To avoid an infinite recursion when importing, create the FunctionDecl
+ // with a simplified function type and update it afterwards.
+ if (FromEPI.ExceptionSpecDecl || FromEPI.ExceptionSpecTemplate ||
+ FromEPI.NoexceptExpr) {
+ FunctionProtoType::ExtProtoInfo DefaultEPI;
+ FromTy = Importer.getFromContext().getFunctionType(
+ FromFPT->getResultType(),
+ FromFPT->arg_type_begin(),
+ FromFPT->arg_type_end() - FromFPT->arg_type_begin(),
+ DefaultEPI);
+ usedDifferentExceptionSpec = true;
+ }
+ }
+
// Import the type.
- QualType T = Importer.Import(D->getType());
+ QualType T = Importer.Import(FromTy);
if (T.isNull())
return 0;
@@ -2572,6 +2717,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
ToFunction->setParams(Parameters);
+ if (usedDifferentExceptionSpec) {
+ // Update FunctionProtoType::ExtProtoInfo.
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return 0;
+ ToFunction->setType(T);
+ }
+
// FIXME: Other bits to merge?
// Add this function to the lexical context.
@@ -2596,6 +2749,25 @@ Decl *ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) {
return VisitCXXMethodDecl(D);
}
+static unsigned getFieldIndex(Decl *F) {
+ RecordDecl *Owner = dyn_cast<RecordDecl>(F->getDeclContext());
+ if (!Owner)
+ return 0;
+
+ unsigned Index = 1;
+ for (DeclContext::decl_iterator D = Owner->noload_decls_begin(),
+ DEnd = Owner->noload_decls_end();
+ D != DEnd; ++D) {
+ if (*D == F)
+ return Index;
+
+ if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D))
+ ++Index;
+ }
+
+ return Index;
+}
+
Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
// Import the major distinguishing characteristics of a variable.
DeclContext *DC, *LexicalDC;
@@ -2609,6 +2781,10 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
DC->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) {
+ // For anonymous fields, match up by index.
+ if (!Name && getFieldIndex(D) != getFieldIndex(FoundField))
+ continue;
+
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundField->getType())) {
Importer.Imported(D, FoundField);
@@ -2642,6 +2818,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
ToField->setLexicalDeclContext(LexicalDC);
if (ToField->hasInClassInitializer())
ToField->setInClassInitializer(D->getInClassInitializer());
+ ToField->setImplicit(D->isImplicit());
Importer.Imported(D, ToField);
LexicalDC->addDeclInternal(ToField);
return ToField;
@@ -2661,6 +2838,10 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (IndirectFieldDecl *FoundField
= dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
+ // For anonymous indirect fields, match up by index.
+ if (!Name && getFieldIndex(D) != getFieldIndex(FoundField))
+ continue;
+
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundField->getType(),
Name)) {
@@ -3025,7 +3206,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
ResultTy, ResultTInfo, DC,
D->isInstanceMethod(),
D->isVariadic(),
- D->isSynthesized(),
+ D->isPropertyAccessor(),
D->isImplicit(),
D->isDefined(),
D->getImplementationControl(),
@@ -4027,7 +4208,8 @@ Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(),
T, E->getValueKind(),
E->getObjectKind(),
- Importer.Import(E->getOperatorLoc()));
+ Importer.Import(E->getOperatorLoc()),
+ E->isFPContractable());
}
Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
@@ -4056,7 +4238,8 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
T, E->getValueKind(),
E->getObjectKind(),
CompLHSType, CompResultType,
- Importer.Import(E->getOperatorLoc()));
+ Importer.Import(E->getOperatorLoc()),
+ E->isFPContractable());
}
static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
@@ -4479,7 +4662,8 @@ FileID ASTImporter::Import(FileID FromID) {
llvm::MemoryBuffer *ToBuf
= llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
FromBuf->getBufferIdentifier());
- ToID = ToSM.createFileIDForMemBuffer(ToBuf);
+ ToID = ToSM.createFileIDForMemBuffer(ToBuf,
+ FromSLoc.getFile().getFileCharacteristic());
}
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index bcc96f9..d20d77e 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -64,7 +64,10 @@ add_dependencies(clangAST
ClangAttrClasses
ClangAttrList
ClangAttrImpl
+ ClangCommentCommandInfo
ClangCommentNodes
+ ClangCommentHTMLTags
+ ClangCommentHTMLTagsProperties
ClangDeclNodes
ClangDiagnosticAST
ClangDiagnosticComment
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index cf3913b..213b214 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/SetVector.h"
#include <algorithm>
#include <set>
@@ -25,13 +26,9 @@ void CXXBasePaths::ComputeDeclsFound() {
assert(NumDeclsFound == 0 && !DeclsFound &&
"Already computed the set of declarations");
- SmallVector<NamedDecl *, 8> Decls;
+ llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8> > Decls;
for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path)
- Decls.push_back(*Path->Decls.first);
-
- // Eliminate duplicated decls.
- llvm::array_pod_sort(Decls.begin(), Decls.end());
- Decls.erase(std::unique(Decls.begin(), Decls.end()), Decls.end());
+ Decls.insert(*Path->Decls.first);
NumDeclsFound = Decls.size();
DeclsFound = new NamedDecl * [NumDeclsFound];
@@ -258,7 +255,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
}
} else if (VisitBase) {
CXXRecordDecl *BaseRecord
- = cast<CXXRecordDecl>(BaseSpec->getType()->getAs<RecordType>()
+ = cast<CXXRecordDecl>(BaseSpec->getType()->castAs<RecordType>()
->getDecl());
if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) {
// C++ [class.member.lookup]p2:
@@ -365,8 +362,8 @@ bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
void *BaseRecord) {
assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
"User data for FindBaseClass is not canonical!");
- return Specifier->getType()->getAs<RecordType>()->getDecl()
- ->getCanonicalDecl() == BaseRecord;
+ return Specifier->getType()->castAs<RecordType>()->getDecl()
+ ->getCanonicalDecl() == BaseRecord;
}
bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
@@ -375,14 +372,15 @@ bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
"User data for FindBaseClass is not canonical!");
return Specifier->isVirtual() &&
- Specifier->getType()->getAs<RecordType>()->getDecl()
- ->getCanonicalDecl() == BaseRecord;
+ Specifier->getType()->castAs<RecordType>()->getDecl()
+ ->getCanonicalDecl() == BaseRecord;
}
bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *Name) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+ RecordDecl *BaseRecord =
+ Specifier->getType()->castAs<RecordType>()->getDecl();
DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
for (Path.Decls = BaseRecord->lookup(N);
@@ -398,7 +396,8 @@ bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *Name) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+ RecordDecl *BaseRecord =
+ Specifier->getType()->castAs<RecordType>()->getDecl();
const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member;
DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
@@ -416,7 +415,8 @@ bool CXXRecordDecl::
FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *Name) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+ RecordDecl *BaseRecord =
+ Specifier->getType()->castAs<RecordType>()->getDecl();
DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
for (Path.Decls = BaseRecord->lookup(N);
@@ -694,7 +694,7 @@ AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
"Cannot get indirect primary bases for class with dependent bases.");
const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
// Only bases with virtual bases participate in computing the
// indirect primary virtual base classes.
@@ -717,7 +717,7 @@ CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const {
"Cannot get indirect primary bases for class with dependent bases.");
const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
// Only bases with virtual bases participate in computing the
// indirect primary virtual base classes.
diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp
index 8a711f0..361f8ac 100644
--- a/lib/AST/Comment.cpp
+++ b/lib/AST/Comment.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Comment.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
@@ -37,11 +38,12 @@ void Comment::dump() const {
// in CommentDumper.cpp, that object file would be removed by linker because
// none of its functions are referenced by other object files, despite the
// LLVM_ATTRIBUTE_USED.
- dump(llvm::errs(), NULL);
+ dump(llvm::errs(), NULL, NULL);
}
-void Comment::dump(SourceManager &SM) const {
- dump(llvm::errs(), &SM);
+void Comment::dump(const ASTContext &Context) const {
+ dump(llvm::errs(), &Context.getCommentCommandTraits(),
+ &Context.getSourceManager());
}
namespace {
@@ -149,13 +151,14 @@ void DeclInfo::fill() {
ParamVars = ArrayRef<const ParmVarDecl *>();
TemplateParameters = NULL;
- if (!ThisDecl) {
+ if (!CommentDecl) {
// If there is no declaration, the defaults is our only guess.
IsFilled = true;
return;
}
-
- Decl::Kind K = ThisDecl->getKind();
+ CurrentDecl = CommentDecl;
+
+ Decl::Kind K = CommentDecl->getKind();
switch (K) {
default:
// Defaults are should be good for declarations we don't handle explicitly.
@@ -165,7 +168,7 @@ void DeclInfo::fill() {
case Decl::CXXConstructor:
case Decl::CXXDestructor:
case Decl::CXXConversion: {
- const FunctionDecl *FD = cast<FunctionDecl>(ThisDecl);
+ const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl);
Kind = FunctionKind;
ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
FD->getNumParams());
@@ -179,14 +182,14 @@ void DeclInfo::fill() {
if (K == Decl::CXXMethod || K == Decl::CXXConstructor ||
K == Decl::CXXDestructor || K == Decl::CXXConversion) {
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(ThisDecl);
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl);
IsInstanceMethod = MD->isInstance();
IsClassMethod = !IsInstanceMethod;
}
break;
}
case Decl::ObjCMethod: {
- const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(ThisDecl);
+ const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl);
Kind = FunctionKind;
ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
MD->param_size());
@@ -197,7 +200,7 @@ void DeclInfo::fill() {
break;
}
case Decl::FunctionTemplate: {
- const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(ThisDecl);
+ const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl);
Kind = FunctionKind;
TemplateKind = Template;
const FunctionDecl *FD = FTD->getTemplatedDecl();
@@ -208,7 +211,7 @@ void DeclInfo::fill() {
break;
}
case Decl::ClassTemplate: {
- const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(ThisDecl);
+ const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl);
Kind = ClassKind;
TemplateKind = Template;
TemplateParameters = CTD->getTemplateParameters();
@@ -216,7 +219,7 @@ void DeclInfo::fill() {
}
case Decl::ClassTemplatePartialSpecialization: {
const ClassTemplatePartialSpecializationDecl *CTPSD =
- cast<ClassTemplatePartialSpecializationDecl>(ThisDecl);
+ cast<ClassTemplatePartialSpecializationDecl>(CommentDecl);
Kind = ClassKind;
TemplateKind = TemplatePartialSpecialization;
TemplateParameters = CTPSD->getTemplateParameters();
@@ -240,12 +243,55 @@ void DeclInfo::fill() {
case Decl::Namespace:
Kind = NamespaceKind;
break;
- case Decl::Typedef:
+ case Decl::Typedef: {
+ Kind = TypedefKind;
+ // If this is a typedef to something we consider a function, extract
+ // arguments and return type.
+ const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl);
+ const TypeSourceInfo *TSI = TD->getTypeSourceInfo();
+ if (!TSI)
+ break;
+ TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
+ while (true) {
+ TL = TL.IgnoreParens();
+ // Look through qualified types.
+ if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
+ TL = QualifiedTL->getUnqualifiedLoc();
+ continue;
+ }
+ // Look through pointer types.
+ if (PointerTypeLoc *PointerTL = dyn_cast<PointerTypeLoc>(&TL)) {
+ TL = PointerTL->getPointeeLoc().getUnqualifiedLoc();
+ continue;
+ }
+ if (BlockPointerTypeLoc *BlockPointerTL =
+ dyn_cast<BlockPointerTypeLoc>(&TL)) {
+ TL = BlockPointerTL->getPointeeLoc().getUnqualifiedLoc();
+ continue;
+ }
+ if (MemberPointerTypeLoc *MemberPointerTL =
+ dyn_cast<MemberPointerTypeLoc>(&TL)) {
+ TL = MemberPointerTL->getPointeeLoc().getUnqualifiedLoc();
+ continue;
+ }
+ // Is this a typedef for a function type?
+ if (FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL)) {
+ Kind = FunctionKind;
+ ArrayRef<ParmVarDecl *> Params = FTL->getParams();
+ ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(),
+ Params.size());
+ ResultType = FTL->getResultLoc().getType();
+ break;
+ }
+ break;
+ }
+ break;
+ }
case Decl::TypeAlias:
Kind = TypedefKind;
break;
case Decl::TypeAliasTemplate: {
- const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(ThisDecl);
+ const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl);
Kind = TypedefKind;
TemplateKind = Template;
TemplateParameters = TAT->getTemplateParameters();
@@ -259,6 +305,25 @@ void DeclInfo::fill() {
IsFilled = true;
}
+StringRef ParamCommandComment::getParamName(const FullComment *FC) const {
+ assert(isParamIndexValid());
+ return FC->getThisDeclInfo()->ParamVars[getParamIndex()]->getName();
+}
+
+StringRef TParamCommandComment::getParamName(const FullComment *FC) const {
+ assert(isPositionValid());
+ const TemplateParameterList *TPL = FC->getThisDeclInfo()->TemplateParameters;
+ for (unsigned i = 0, e = getDepth(); i != e; ++i) {
+ if (i == e-1)
+ return TPL->getParam(getIndex(i))->getName();
+ const NamedDecl *Param = TPL->getParam(getIndex(i));
+ if (const TemplateTemplateParmDecl *TTP =
+ dyn_cast<TemplateTemplateParmDecl>(Param))
+ TPL = TTP->getTemplateParameters();
+ }
+ return "";
+}
+
} // end namespace comments
} // end namespace clang
diff --git a/lib/AST/CommentBriefParser.cpp b/lib/AST/CommentBriefParser.cpp
index 0aebc1e..95daa7e 100644
--- a/lib/AST/CommentBriefParser.cpp
+++ b/lib/AST/CommentBriefParser.cpp
@@ -15,6 +15,11 @@ namespace clang {
namespace comments {
namespace {
+inline bool isWhitespace(char C) {
+ return C == ' ' || C == '\n' || C == '\r' ||
+ C == '\t' || C == '\f' || C == '\v';
+}
+
/// Convert all whitespace into spaces, remove leading and trailing spaces,
/// compress multiple spaces into one.
void cleanupBrief(std::string &S) {
@@ -23,8 +28,7 @@ void cleanupBrief(std::string &S) {
for (std::string::iterator I = S.begin(), E = S.end();
I != E; ++I) {
const char C = *I;
- if (C == ' ' || C == '\n' || C == '\r' ||
- C == '\t' || C == '\v' || C == '\f') {
+ if (isWhitespace(C)) {
if (!PrevWasSpace) {
*O++ = ' ';
PrevWasSpace = true;
@@ -40,6 +44,15 @@ void cleanupBrief(std::string &S) {
S.resize(O - S.begin());
}
+
+bool isWhitespace(StringRef Text) {
+ for (StringRef::const_iterator I = Text.begin(), E = Text.end();
+ I != E; ++I) {
+ if (!isWhitespace(*I))
+ return false;
+ }
+ return true;
+}
} // unnamed namespace
BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) :
@@ -66,19 +79,23 @@ std::string BriefParser::Parse() {
}
if (Tok.is(tok::command)) {
- StringRef Name = Tok.getCommandName();
- if (Traits.isBriefCommand(Name)) {
+ const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
+ if (Info->IsBriefCommand) {
FirstParagraphOrBrief.clear();
InBrief = true;
ConsumeToken();
continue;
}
- if (Traits.isReturnsCommand(Name)) {
+ if (Info->IsReturnsCommand) {
InReturns = true;
+ InBrief = false;
+ InFirstParagraph = false;
ReturnsParagraph += "Returns ";
+ ConsumeToken();
+ continue;
}
// Block commands implicitly start a new paragraph.
- if (Traits.isBlockCommand(Name)) {
+ if (Info->IsBlockCommand) {
// We found an implicit paragraph end.
InFirstParagraph = false;
if (InBrief)
@@ -93,13 +110,29 @@ std::string BriefParser::Parse() {
ReturnsParagraph += ' ';
ConsumeToken();
+ // If the next token is a whitespace only text, ignore it. Thus we allow
+ // two paragraphs to be separated by line that has only whitespace in it.
+ //
+ // We don't need to add a space to the parsed text because we just added
+ // a space for the newline.
+ if (Tok.is(tok::text)) {
+ if (isWhitespace(Tok.getText()))
+ ConsumeToken();
+ }
+
if (Tok.is(tok::newline)) {
ConsumeToken();
- // We found a paragraph end.
- InFirstParagraph = false;
- InReturns = false;
+ // We found a paragraph end. This ends the brief description if
+ // \\brief command or its equivalent was explicitly used.
+ // Stop scanning text because an explicit \\brief paragraph is the
+ // preffered one.
if (InBrief)
break;
+ // End first paragraph if we found some non-whitespace text.
+ if (InFirstParagraph && !isWhitespace(FirstParagraphOrBrief))
+ InFirstParagraph = false;
+ // End the \\returns paragraph because we found the paragraph end.
+ InReturns = false;
}
continue;
}
diff --git a/lib/AST/CommentCommandTraits.cpp b/lib/AST/CommentCommandTraits.cpp
index dc7a0bd..e7e40fd 100644
--- a/lib/AST/CommentCommandTraits.cpp
+++ b/lib/AST/CommentCommandTraits.cpp
@@ -8,125 +8,64 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/CommentCommandTraits.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/STLExtras.h"
namespace clang {
namespace comments {
-// TODO: tablegen
+#include "clang/AST/CommentCommandInfo.inc"
-bool CommandTraits::isVerbatimBlockCommand(StringRef StartName,
- StringRef &EndName) const {
- const char *Result = llvm::StringSwitch<const char *>(StartName)
- .Case("code", "endcode")
- .Case("verbatim", "endverbatim")
- .Case("htmlonly", "endhtmlonly")
- .Case("latexonly", "endlatexonly")
- .Case("xmlonly", "endxmlonly")
- .Case("manonly", "endmanonly")
- .Case("rtfonly", "endrtfonly")
+CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator) :
+ NextID(llvm::array_lengthof(Commands)), Allocator(Allocator)
+{ }
- .Case("dot", "enddot")
- .Case("msc", "endmsc")
-
- .Case("f$", "f$") // Inline LaTeX formula
- .Case("f[", "f]") // Displayed LaTeX formula
- .Case("f{", "f}") // LaTeX environment
-
- .Default(NULL);
-
- if (Result) {
- EndName = Result;
- return true;
- }
-
- for (VerbatimBlockCommandVector::const_iterator
- I = VerbatimBlockCommands.begin(),
- E = VerbatimBlockCommands.end();
- I != E; ++I)
- if (I->StartName == StartName) {
- EndName = I->EndName;
- return true;
- }
-
- return false;
+const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const {
+ if (const CommandInfo *Info = getBuiltinCommandInfo(Name))
+ return Info;
+ return getRegisteredCommandInfo(Name);
}
-bool CommandTraits::isVerbatimLineCommand(StringRef Name) const {
- bool Result = isDeclarationCommand(Name) || llvm::StringSwitch<bool>(Name)
- .Case("defgroup", true)
- .Case("ingroup", true)
- .Case("addtogroup", true)
- .Case("weakgroup", true)
- .Case("name", true)
-
- .Case("section", true)
- .Case("subsection", true)
- .Case("subsubsection", true)
- .Case("paragraph", true)
-
- .Case("mainpage", true)
- .Case("subpage", true)
- .Case("ref", true)
+const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const {
+ if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID))
+ return Info;
+ return getRegisteredCommandInfo(CommandID);
+}
- .Default(false);
+const CommandInfo *CommandTraits::registerUnknownCommand(StringRef CommandName) {
+ char *Name = Allocator.Allocate<char>(CommandName.size() + 1);
+ memcpy(Name, CommandName.data(), CommandName.size());
+ Name[CommandName.size()] = '\0';
- if (Result)
- return true;
+ // Value-initialize (=zero-initialize in this case) a new CommandInfo.
+ CommandInfo *Info = new (Allocator) CommandInfo();
+ Info->Name = Name;
+ Info->ID = NextID++;
+ Info->IsUnknownCommand = true;
- for (VerbatimLineCommandVector::const_iterator
- I = VerbatimLineCommands.begin(),
- E = VerbatimLineCommands.end();
- I != E; ++I)
- if (I->Name == Name)
- return true;
+ RegisteredCommands.push_back(Info);
- return false;
+ return Info;
}
-bool CommandTraits::isDeclarationCommand(StringRef Name) const {
- return llvm::StringSwitch<bool>(Name)
- // Doxygen commands.
- .Case("fn", true)
- .Case("var", true)
- .Case("property", true)
- .Case("typedef", true)
-
- .Case("overload", true)
-
- // HeaderDoc commands.
- .Case("class", true)
- .Case("interface", true)
- .Case("protocol", true)
- .Case("category", true)
- .Case("template", true)
- .Case("function", true)
- .Case("method", true)
- .Case("callback", true)
- .Case("var", true)
- .Case("const", true)
- .Case("constant", true)
- .Case("property", true)
- .Case("struct", true)
- .Case("union", true)
- .Case("typedef", true)
- .Case("enum", true)
-
- .Default(false);
+const CommandInfo *CommandTraits::getBuiltinCommandInfo(
+ unsigned CommandID) {
+ if (CommandID < llvm::array_lengthof(Commands))
+ return &Commands[CommandID];
+ return NULL;
}
-void CommandTraits::addVerbatimBlockCommand(StringRef StartName,
- StringRef EndName) {
- VerbatimBlockCommand VBC;
- VBC.StartName = StartName;
- VBC.EndName = EndName;
- VerbatimBlockCommands.push_back(VBC);
+const CommandInfo *CommandTraits::getRegisteredCommandInfo(
+ StringRef Name) const {
+ for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) {
+ if (RegisteredCommands[i]->Name == Name)
+ return RegisteredCommands[i];
+ }
+ return NULL;
}
-void CommandTraits::addVerbatimLineCommand(StringRef Name) {
- VerbatimLineCommand VLC;
- VLC.Name = Name;
- VerbatimLineCommands.push_back(VLC);
+const CommandInfo *CommandTraits::getRegisteredCommandInfo(
+ unsigned CommandID) const {
+ return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)];
}
} // end namespace comments
diff --git a/lib/AST/CommentDumper.cpp b/lib/AST/CommentDumper.cpp
index dffc823..19d24b2 100644
--- a/lib/AST/CommentDumper.cpp
+++ b/lib/AST/CommentDumper.cpp
@@ -16,12 +16,20 @@ namespace comments {
namespace {
class CommentDumper: public comments::ConstCommentVisitor<CommentDumper> {
raw_ostream &OS;
- SourceManager *SM;
+ const CommandTraits *Traits;
+ const SourceManager *SM;
+
+ /// The \c FullComment parent of the comment being dumped.
+ const FullComment *FC;
+
unsigned IndentLevel;
public:
- CommentDumper(raw_ostream &OS, SourceManager *SM) :
- OS(OS), SM(SM), IndentLevel(0)
+ CommentDumper(raw_ostream &OS,
+ const CommandTraits *Traits,
+ const SourceManager *SM,
+ const FullComment *FC) :
+ OS(OS), Traits(Traits), SM(SM), FC(FC), IndentLevel(0)
{ }
void dumpIndent() const {
@@ -56,6 +64,15 @@ public:
void visitVerbatimLineComment(const VerbatimLineComment *C);
void visitFullComment(const FullComment *C);
+
+ const char *getCommandName(unsigned CommandID) {
+ if (Traits)
+ return Traits->getCommandInfo(CommandID)->Name;
+ const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
+ if (Info)
+ return Info->Name;
+ return "<not a builtin command>";
+ }
};
void CommentDumper::dumpSourceRange(const Comment *C) {
@@ -107,7 +124,7 @@ void CommentDumper::visitTextComment(const TextComment *C) {
void CommentDumper::visitInlineCommandComment(const InlineCommandComment *C) {
dumpComment(C);
- OS << " Name=\"" << C->getCommandName() << "\"";
+ OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
switch (C->getRenderKind()) {
case InlineCommandComment::RenderNormal:
OS << " RenderNormal";
@@ -155,7 +172,7 @@ void CommentDumper::visitParagraphComment(const ParagraphComment *C) {
void CommentDumper::visitBlockCommandComment(const BlockCommandComment *C) {
dumpComment(C);
- OS << " Name=\"" << C->getCommandName() << "\"";
+ OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
}
@@ -170,8 +187,12 @@ void CommentDumper::visitParamCommandComment(const ParamCommandComment *C) {
else
OS << " implicitly";
- if (C->hasParamName())
- OS << " Param=\"" << C->getParamName() << "\"";
+ if (C->hasParamName()) {
+ if (C->isParamIndexValid())
+ OS << " Param=\"" << C->getParamName(FC) << "\"";
+ else
+ OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
+ }
if (C->isParamIndexValid())
OS << " ParamIndex=" << C->getParamIndex();
@@ -181,7 +202,10 @@ void CommentDumper::visitTParamCommandComment(const TParamCommandComment *C) {
dumpComment(C);
if (C->hasParamName()) {
- OS << " Param=\"" << C->getParamName() << "\"";
+ if (C->isPositionValid())
+ OS << " Param=\"" << C->getParamName(FC) << "\"";
+ else
+ OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
}
if (C->isPositionValid()) {
@@ -198,7 +222,7 @@ void CommentDumper::visitTParamCommandComment(const TParamCommandComment *C) {
void CommentDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) {
dumpComment(C);
- OS << " Name=\"" << C->getCommandName() << "\""
+ OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""
" CloseName=\"" << C->getCloseName() << "\"";
}
@@ -220,8 +244,10 @@ void CommentDumper::visitFullComment(const FullComment *C) {
} // unnamed namespace
-void Comment::dump(llvm::raw_ostream &OS, SourceManager *SM) const {
- CommentDumper D(llvm::errs(), SM);
+void Comment::dump(llvm::raw_ostream &OS, const CommandTraits *Traits,
+ const SourceManager *SM) const {
+ const FullComment *FC = dyn_cast<FullComment>(this);
+ CommentDumper D(llvm::errs(), Traits, SM, FC);
D.dumpSubtree(this);
llvm::errs() << '\n';
}
diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp
index b6516ec..31a09f7 100644
--- a/lib/AST/CommentLexer.cpp
+++ b/lib/AST/CommentLexer.cpp
@@ -28,6 +28,9 @@ bool isHTMLHexCharacterReferenceCharacter(char C) {
(C >= 'a' && C <= 'f') ||
(C >= 'A' && C <= 'F');
}
+
+#include "clang/AST/CommentHTMLTags.inc"
+
} // unnamed namespace
StringRef Lexer::resolveHTMLNamedCharacterReference(StringRef Name) const {
@@ -223,6 +226,11 @@ bool isWhitespace(const char *BufferPtr, const char *BufferEnd) {
return skipWhitespace(BufferPtr, BufferEnd) == BufferEnd;
}
+bool isCommandNameStartCharacter(char C) {
+ return (C >= 'a' && C <= 'z') ||
+ (C >= 'A' && C <= 'Z');
+}
+
bool isCommandNameCharacter(char C) {
return (C >= 'a' && C <= 'z') ||
(C >= 'A' && C <= 'Z') ||
@@ -337,7 +345,7 @@ void Lexer::lexCommentText(Token &T) {
}
// Don't make zero-length commands.
- if (!isCommandNameCharacter(*TokenPtr)) {
+ if (!isCommandNameStartCharacter(*TokenPtr)) {
formTextToken(T, TokenPtr);
return;
}
@@ -356,18 +364,23 @@ void Lexer::lexCommentText(Token &T) {
}
const StringRef CommandName(BufferPtr + 1, Length);
- StringRef EndName;
- if (Traits.isVerbatimBlockCommand(CommandName, EndName)) {
- setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, EndName);
+ const CommandInfo *Info = Traits.getCommandInfoOrNULL(CommandName);
+ if (!Info) {
+ formTokenWithChars(T, TokenPtr, tok::unknown_command);
+ T.setUnknownCommandName(CommandName);
+ return;
+ }
+ if (Info->IsVerbatimBlockCommand) {
+ setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, Info);
return;
}
- if (Traits.isVerbatimLineCommand(CommandName)) {
- setupAndLexVerbatimLine(T, TokenPtr);
+ if (Info->IsVerbatimLineCommand) {
+ setupAndLexVerbatimLine(T, TokenPtr, Info);
return;
}
formTokenWithChars(T, TokenPtr, tok::command);
- T.setCommandName(CommandName);
+ T.setCommandID(Info->getID());
return;
}
@@ -420,14 +433,15 @@ void Lexer::lexCommentText(Token &T) {
void Lexer::setupAndLexVerbatimBlock(Token &T,
const char *TextBegin,
- char Marker, StringRef EndName) {
+ char Marker, const CommandInfo *Info) {
+ assert(Info->IsVerbatimBlockCommand);
+
VerbatimBlockEndCommandName.clear();
VerbatimBlockEndCommandName.append(Marker == '\\' ? "\\" : "@");
- VerbatimBlockEndCommandName.append(EndName);
+ VerbatimBlockEndCommandName.append(Info->EndCommandName);
- StringRef Name(BufferPtr + 1, TextBegin - (BufferPtr + 1));
formTokenWithChars(T, TextBegin, tok::verbatim_block_begin);
- T.setVerbatimBlockName(Name);
+ T.setVerbatimBlockID(Info->getID());
// If there is a newline following the verbatim opening command, skip the
// newline so that we don't create an tok::verbatim_block_line with empty
@@ -468,7 +482,7 @@ again:
const char *End = BufferPtr + VerbatimBlockEndCommandName.size();
StringRef Name(BufferPtr + 1, End - (BufferPtr + 1));
formTokenWithChars(T, End, tok::verbatim_block_end);
- T.setVerbatimBlockName(Name);
+ T.setVerbatimBlockID(Traits.getCommandInfo(Name)->getID());
State = LS_Normal;
return;
} else {
@@ -498,10 +512,11 @@ void Lexer::lexVerbatimBlockBody(Token &T) {
lexVerbatimBlockFirstLine(T);
}
-void Lexer::setupAndLexVerbatimLine(Token &T, const char *TextBegin) {
- const StringRef Name(BufferPtr + 1, TextBegin - BufferPtr - 1);
+void Lexer::setupAndLexVerbatimLine(Token &T, const char *TextBegin,
+ const CommandInfo *Info) {
+ assert(Info->IsVerbatimLineCommand);
formTokenWithChars(T, TextBegin, tok::verbatim_line_name);
- T.setVerbatimLineName(Name);
+ T.setVerbatimLineID(Info->getID());
State = LS_VerbatimLineText;
}
@@ -585,8 +600,12 @@ void Lexer::setupAndLexHTMLStartTag(Token &T) {
assert(BufferPtr[0] == '<' &&
isHTMLIdentifierStartingCharacter(BufferPtr[1]));
const char *TagNameEnd = skipHTMLIdentifier(BufferPtr + 2, CommentEnd);
-
StringRef Name(BufferPtr + 1, TagNameEnd - (BufferPtr + 1));
+ if (!isHTMLTagName(Name)) {
+ formTextToken(T, TagNameEnd);
+ return;
+ }
+
formTokenWithChars(T, TagNameEnd, tok::html_start_tag);
T.setHTMLTagStartName(Name);
@@ -665,11 +684,16 @@ void Lexer::setupAndLexHTMLEndTag(Token &T) {
const char *TagNameBegin = skipWhitespace(BufferPtr + 2, CommentEnd);
const char *TagNameEnd = skipHTMLIdentifier(TagNameBegin, CommentEnd);
+ StringRef Name(TagNameBegin, TagNameEnd - TagNameBegin);
+ if (!isHTMLTagName(Name)) {
+ formTextToken(T, TagNameEnd);
+ return;
+ }
const char *End = skipWhitespace(TagNameEnd, CommentEnd);
formTokenWithChars(T, End, tok::html_end_tag);
- T.setHTMLTagEndName(StringRef(TagNameBegin, TagNameEnd - TagNameBegin));
+ T.setHTMLTagEndName(Name);
if (BufferPtr != CommentEnd && *BufferPtr == '>')
State = LS_HTMLEndTag;
@@ -683,11 +707,11 @@ void Lexer::lexHTMLEndTag(Token &T) {
}
Lexer::Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits,
- SourceLocation FileLoc, const CommentOptions &CommOpts,
+ SourceLocation FileLoc,
const char *BufferStart, const char *BufferEnd):
Allocator(Allocator), Traits(Traits),
BufferStart(BufferStart), BufferEnd(BufferEnd),
- FileLoc(FileLoc), CommOpts(CommOpts), BufferPtr(BufferStart),
+ FileLoc(FileLoc), BufferPtr(BufferStart),
CommentState(LCS_BeforeComment), State(LS_Normal) {
}
diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp
index 43abf6a..d0a8474 100644
--- a/lib/AST/CommentParser.cpp
+++ b/lib/AST/CommentParser.cpp
@@ -132,8 +132,8 @@ class TextTokenRetokenizer {
Result.setKind(tok::text);
Result.setLength(TokLength);
#ifndef NDEBUG
- Result.TextPtr1 = "<UNSET>";
- Result.TextLen1 = 7;
+ Result.TextPtr = "<UNSET>";
+ Result.IntVal = 7;
#endif
Result.setText(Text);
}
@@ -312,26 +312,26 @@ BlockCommandComment *Parser::parseBlockCommand() {
BlockCommandComment *BC;
bool IsParam = false;
bool IsTParam = false;
- unsigned NumArgs = 0;
- if (Traits.isParamCommand(Tok.getCommandName())) {
+ const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
+ if (Info->IsParamCommand) {
IsParam = true;
PC = S.actOnParamCommandStart(Tok.getLocation(),
Tok.getEndLocation(),
- Tok.getCommandName());
- } if (Traits.isTParamCommand(Tok.getCommandName())) {
+ Tok.getCommandID());
+ } if (Info->IsTParamCommand) {
IsTParam = true;
TPC = S.actOnTParamCommandStart(Tok.getLocation(),
Tok.getEndLocation(),
- Tok.getCommandName());
+ Tok.getCommandID());
} else {
- NumArgs = Traits.getBlockCommandNumArgs(Tok.getCommandName());
BC = S.actOnBlockCommandStart(Tok.getLocation(),
Tok.getEndLocation(),
- Tok.getCommandName());
+ Tok.getCommandID());
}
consumeToken();
- if (Tok.is(tok::command) && Traits.isBlockCommand(Tok.getCommandName())) {
+ if (Tok.is(tok::command) &&
+ Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand) {
// Block command ahead. We can't nest block commands, so pretend that this
// command has an empty argument.
ParagraphComment *Paragraph = S.actOnParagraphComment(
@@ -348,7 +348,7 @@ BlockCommandComment *Parser::parseBlockCommand() {
}
}
- if (IsParam || IsTParam || NumArgs > 0) {
+ if (IsParam || IsTParam || Info->NumArgs > 0) {
// In order to parse command arguments we need to retokenize a few
// following text tokens.
TextTokenRetokenizer Retokenizer(Allocator, *this);
@@ -358,7 +358,7 @@ BlockCommandComment *Parser::parseBlockCommand() {
else if (IsTParam)
parseTParamCommandArgs(TPC, Retokenizer);
else
- parseBlockCommandArgs(BC, Retokenizer, NumArgs);
+ parseBlockCommandArgs(BC, Retokenizer, Info->NumArgs);
Retokenizer.putBackLeftoverTokens();
}
@@ -394,14 +394,14 @@ InlineCommandComment *Parser::parseInlineCommand() {
if (ArgTokValid) {
IC = S.actOnInlineCommand(CommandTok.getLocation(),
CommandTok.getEndLocation(),
- CommandTok.getCommandName(),
+ CommandTok.getCommandID(),
ArgTok.getLocation(),
ArgTok.getEndLocation(),
ArgTok.getText());
} else {
IC = S.actOnInlineCommand(CommandTok.getLocation(),
CommandTok.getEndLocation(),
- CommandTok.getCommandName());
+ CommandTok.getCommandID());
}
Retokenizer.putBackLeftoverTokens();
@@ -540,23 +540,39 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() {
assert(Content.size() != 0);
break; // Block content or EOF ahead, finish this parapgaph.
- case tok::command:
- if (Traits.isBlockCommand(Tok.getCommandName())) {
+ case tok::unknown_command:
+ Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
+ Tok.getEndLocation(),
+ Tok.getUnknownCommandName()));
+ consumeToken();
+ continue;
+
+ case tok::command: {
+ const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
+ if (Info->IsBlockCommand) {
if (Content.size() == 0)
return parseBlockCommand();
break; // Block command ahead, finish this parapgaph.
}
- if (Traits.isInlineCommand(Tok.getCommandName())) {
- Content.push_back(parseInlineCommand());
+ if (Info->IsVerbatimBlockEndCommand) {
+ Diag(Tok.getLocation(),
+ diag::warn_verbatim_block_end_without_start)
+ << Info->Name
+ << SourceRange(Tok.getLocation(), Tok.getEndLocation());
+ consumeToken();
continue;
}
-
- // Not a block command, not an inline command ==> an unknown command.
- Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
- Tok.getEndLocation(),
- Tok.getCommandName()));
- consumeToken();
+ if (Info->IsUnknownCommand) {
+ Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
+ Tok.getEndLocation(),
+ Info->getID()));
+ consumeToken();
+ continue;
+ }
+ assert(Info->IsInlineCommand);
+ Content.push_back(parseInlineCommand());
continue;
+ }
case tok::newline: {
consumeToken();
@@ -606,7 +622,7 @@ VerbatimBlockComment *Parser::parseVerbatimBlock() {
VerbatimBlockComment *VB =
S.actOnVerbatimBlockStart(Tok.getLocation(),
- Tok.getVerbatimBlockName());
+ Tok.getVerbatimBlockID());
consumeToken();
// Don't create an empty line if verbatim opening command is followed
@@ -634,8 +650,9 @@ VerbatimBlockComment *Parser::parseVerbatimBlock() {
}
if (Tok.is(tok::verbatim_block_end)) {
+ const CommandInfo *Info = Traits.getCommandInfo(Tok.getVerbatimBlockID());
S.actOnVerbatimBlockFinish(VB, Tok.getLocation(),
- Tok.getVerbatimBlockName(),
+ Info->Name,
S.copyArray(llvm::makeArrayRef(Lines)));
consumeToken();
} else {
@@ -666,7 +683,7 @@ VerbatimLineComment *Parser::parseVerbatimLine() {
}
VerbatimLineComment *VL = S.actOnVerbatimLine(NameTok.getLocation(),
- NameTok.getVerbatimLineName(),
+ NameTok.getVerbatimLineID(),
TextBegin,
Text);
consumeToken();
@@ -676,6 +693,7 @@ VerbatimLineComment *Parser::parseVerbatimLine() {
BlockContentComment *Parser::parseBlockContent() {
switch (Tok.getKind()) {
case tok::text:
+ case tok::unknown_command:
case tok::command:
case tok::html_start_tag:
case tok::html_end_tag:
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index c39ee57..08ecb3a 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -13,15 +13,22 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/SmallString.h"
namespace clang {
namespace comments {
+namespace {
+#include "clang/AST/CommentHTMLTagsProperties.inc"
+} // unnamed namespace
+
Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
- DiagnosticsEngine &Diags, const CommandTraits &Traits) :
+ DiagnosticsEngine &Diags, CommandTraits &Traits,
+ const Preprocessor *PP) :
Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
- ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) {
+ PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) {
}
void Sema::setDecl(const Decl *D) {
@@ -29,7 +36,7 @@ void Sema::setDecl(const Decl *D) {
return;
ThisDeclInfo = new (Allocator) DeclInfo;
- ThisDeclInfo->ThisDecl = D;
+ ThisDeclInfo->CommentDecl = D;
ThisDeclInfo->IsFilled = false;
}
@@ -40,8 +47,8 @@ ParagraphComment *Sema::actOnParagraphComment(
BlockCommandComment *Sema::actOnBlockCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) {
- return new (Allocator) BlockCommandComment(LocBegin, LocEnd, Name);
+ unsigned CommandID) {
+ return new (Allocator) BlockCommandComment(LocBegin, LocEnd, CommandID);
}
void Sema::actOnBlockCommandArgs(BlockCommandComment *Command,
@@ -55,18 +62,19 @@ void Sema::actOnBlockCommandFinish(BlockCommandComment *Command,
checkBlockCommandEmptyParagraph(Command);
checkBlockCommandDuplicate(Command);
checkReturnsCommand(Command);
+ checkDeprecatedCommand(Command);
}
ParamCommandComment *Sema::actOnParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) {
+ unsigned CommandID) {
ParamCommandComment *Command =
- new (Allocator) ParamCommandComment(LocBegin, LocEnd, Name);
+ new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID);
if (!isFunctionDecl())
Diag(Command->getLocation(),
diag::warn_doc_param_not_attached_to_a_function_decl)
- << Command->getCommandNameRange();
+ << Command->getCommandNameRange(Traits);
return Command;
}
@@ -142,56 +150,6 @@ void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command,
ArgLocEnd),
Arg);
Command->setArgs(llvm::makeArrayRef(A, 1));
-
- if (!isFunctionDecl()) {
- // We already warned that this \\param is not attached to a function decl.
- return;
- }
-
- ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
-
- // Check that referenced parameter name is in the function decl.
- const unsigned ResolvedParamIndex = resolveParmVarReference(Arg, ParamVars);
- if (ResolvedParamIndex != ParamCommandComment::InvalidParamIndex) {
- Command->setParamIndex(ResolvedParamIndex);
- if (ParamVarDocs[ResolvedParamIndex]) {
- SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
- Diag(ArgLocBegin, diag::warn_doc_param_duplicate)
- << Arg << ArgRange;
- ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
- Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
- << PrevCommand->getParamNameRange();
- }
- ParamVarDocs[ResolvedParamIndex] = Command;
- return;
- }
-
- SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
- Diag(ArgLocBegin, diag::warn_doc_param_not_found)
- << Arg << ArgRange;
-
- // No parameters -- can't suggest a correction.
- if (ParamVars.size() == 0)
- return;
-
- unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
- if (ParamVars.size() == 1) {
- // If function has only one parameter then only that parameter
- // can be documented.
- CorrectedParamIndex = 0;
- } else {
- // Do typo correction.
- CorrectedParamIndex = correctTypoInParmVarReference(Arg, ParamVars);
- }
- if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
- const ParmVarDecl *CorrectedPVD = ParamVars[CorrectedParamIndex];
- if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
- Diag(ArgLocBegin, diag::note_doc_param_name_suggestion)
- << CorrectedII->getName()
- << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
- }
-
- return;
}
void Sema::actOnParamCommandFinish(ParamCommandComment *Command,
@@ -202,14 +160,14 @@ void Sema::actOnParamCommandFinish(ParamCommandComment *Command,
TParamCommandComment *Sema::actOnTParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) {
+ unsigned CommandID) {
TParamCommandComment *Command =
- new (Allocator) TParamCommandComment(LocBegin, LocEnd, Name);
+ new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID);
if (!isTemplateOrSpecialization())
Diag(Command->getLocation(),
diag::warn_doc_tparam_not_attached_to_a_template_decl)
- << Command->getCommandNameRange();
+ << Command->getCommandNameRange(Traits);
return Command;
}
@@ -285,19 +243,20 @@ void Sema::actOnTParamCommandFinish(TParamCommandComment *Command,
InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
- StringRef CommandName) {
+ unsigned CommandID) {
ArrayRef<InlineCommandComment::Argument> Args;
+ StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
return new (Allocator) InlineCommandComment(
CommandLocBegin,
CommandLocEnd,
- CommandName,
+ CommandID,
getInlineCommandRenderKind(CommandName),
Args);
}
InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
- StringRef CommandName,
+ unsigned CommandID,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg) {
@@ -305,21 +264,29 @@ InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
ArgLocEnd),
Arg);
+ StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
return new (Allocator) InlineCommandComment(
CommandLocBegin,
CommandLocEnd,
- CommandName,
+ CommandID,
getInlineCommandRenderKind(CommandName),
llvm::makeArrayRef(A, 1));
}
InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
SourceLocation LocEnd,
- StringRef Name) {
+ StringRef CommandName) {
+ unsigned CommandID = Traits.registerUnknownCommand(CommandName)->getID();
+ return actOnUnknownCommand(LocBegin, LocEnd, CommandID);
+}
+
+InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID) {
ArrayRef<InlineCommandComment::Argument> Args;
return new (Allocator) InlineCommandComment(
- LocBegin, LocEnd, Name,
+ LocBegin, LocEnd, CommandID,
InlineCommandComment::RenderNormal,
Args);
}
@@ -331,11 +298,12 @@ TextComment *Sema::actOnText(SourceLocation LocBegin,
}
VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc,
- StringRef Name) {
+ unsigned CommandID) {
+ StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
return new (Allocator) VerbatimBlockComment(
Loc,
- Loc.getLocWithOffset(1 + Name.size()),
- Name);
+ Loc.getLocWithOffset(1 + CommandName.size()),
+ CommandID);
}
VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc,
@@ -353,13 +321,13 @@ void Sema::actOnVerbatimBlockFinish(
}
VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin,
- StringRef Name,
+ unsigned CommandID,
SourceLocation TextBegin,
StringRef Text) {
return new (Allocator) VerbatimLineComment(
LocBegin,
TextBegin.getLocWithOffset(Text.size()),
- Name,
+ CommandID,
TextBegin,
Text);
}
@@ -445,30 +413,35 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin,
FullComment *Sema::actOnFullComment(
ArrayRef<BlockContentComment *> Blocks) {
- return new (Allocator) FullComment(Blocks, ThisDeclInfo);
+ FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
+ resolveParamCommandIndexes(FC);
+ return FC;
}
void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
+ if (Traits.getCommandInfo(Command->getCommandID())->IsEmptyParagraphAllowed)
+ return;
+
ParagraphComment *Paragraph = Command->getParagraph();
if (Paragraph->isWhitespace()) {
SourceLocation DiagLoc;
if (Command->getNumArgs() > 0)
DiagLoc = Command->getArgRange(Command->getNumArgs() - 1).getEnd();
if (!DiagLoc.isValid())
- DiagLoc = Command->getCommandNameRange().getEnd();
+ DiagLoc = Command->getCommandNameRange(Traits).getEnd();
Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
- << Command->getCommandName()
+ << Command->getCommandName(Traits)
<< Command->getSourceRange();
}
}
void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
- if (!Traits.isReturnsCommand(Command->getCommandName()))
+ if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand)
return;
if (isFunctionDecl()) {
if (ThisDeclInfo->ResultType->isVoidType()) {
unsigned DiagKind;
- switch (ThisDeclInfo->ThisDecl->getKind()) {
+ switch (ThisDeclInfo->CommentDecl->getKind()) {
default:
if (ThisDeclInfo->IsObjCMethod)
DiagKind = 3;
@@ -484,7 +457,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
}
Diag(Command->getLocation(),
diag::warn_doc_returns_attached_to_a_void_function)
- << Command->getCommandName()
+ << Command->getCommandName(Traits)
<< DiagKind
<< Command->getSourceRange();
}
@@ -492,20 +465,20 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
}
Diag(Command->getLocation(),
diag::warn_doc_returns_not_attached_to_a_function_decl)
- << Command->getCommandName()
+ << Command->getCommandName(Traits)
<< Command->getSourceRange();
}
void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
- StringRef Name = Command->getCommandName();
+ const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
const BlockCommandComment *PrevCommand = NULL;
- if (Traits.isBriefCommand(Name)) {
+ if (Info->IsBriefCommand) {
if (!BriefCommand) {
BriefCommand = Command;
return;
}
PrevCommand = BriefCommand;
- } else if (Traits.isReturnsCommand(Name)) {
+ } else if (Info->IsReturnsCommand) {
if (!ReturnsCommand) {
ReturnsCommand = Command;
return;
@@ -515,18 +488,153 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
// We don't want to check this command for duplicates.
return;
}
+ StringRef CommandName = Command->getCommandName(Traits);
+ StringRef PrevCommandName = PrevCommand->getCommandName(Traits);
Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
- << Name
+ << CommandName
<< Command->getSourceRange();
- if (Name == PrevCommand->getCommandName())
+ if (CommandName == PrevCommandName)
Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
- << PrevCommand->getCommandName()
- << Command->getSourceRange();
+ << PrevCommandName
+ << PrevCommand->getSourceRange();
else
Diag(PrevCommand->getLocation(),
diag::note_doc_block_command_previous_alias)
- << PrevCommand->getCommandName()
- << Name;
+ << PrevCommandName
+ << CommandName;
+}
+
+void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {
+ if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand)
+ return;
+
+ const Decl *D = ThisDeclInfo->CommentDecl;
+ if (!D)
+ return;
+
+ if (D->hasAttr<DeprecatedAttr>() ||
+ D->hasAttr<AvailabilityAttr>() ||
+ D->hasAttr<UnavailableAttr>())
+ return;
+
+ Diag(Command->getLocation(),
+ diag::warn_doc_deprecated_not_sync)
+ << Command->getSourceRange();
+
+ // Try to emit a fixit with a deprecation attribute.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // Don't emit a Fix-It for non-member function definitions. GCC does not
+ // accept attributes on them.
+ const DeclContext *Ctx = FD->getDeclContext();
+ if ((!Ctx || !Ctx->isRecord()) &&
+ FD->doesThisDeclarationHaveABody())
+ return;
+
+ StringRef AttributeSpelling = "__attribute__((deprecated))";
+ if (PP) {
+ TokenValue Tokens[] = {
+ tok::kw___attribute, tok::l_paren, tok::l_paren,
+ PP->getIdentifierInfo("deprecated"),
+ tok::r_paren, tok::r_paren
+ };
+ StringRef MacroName = PP->getLastMacroWithSpelling(FD->getLocation(),
+ Tokens);
+ if (!MacroName.empty())
+ AttributeSpelling = MacroName;
+ }
+
+ SmallString<64> TextToInsert(" ");
+ TextToInsert += AttributeSpelling;
+ Diag(FD->getLocEnd(),
+ diag::note_add_deprecation_attr)
+ << FixItHint::CreateInsertion(FD->getLocEnd().getLocWithOffset(1),
+ TextToInsert);
+ }
+}
+
+void Sema::resolveParamCommandIndexes(const FullComment *FC) {
+ if (!isFunctionDecl()) {
+ // We already warned that \\param commands are not attached to a function
+ // decl.
+ return;
+ }
+
+ llvm::SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;
+
+ // Comment AST nodes that correspond to \c ParamVars for which we have
+ // found a \\param command or NULL if no documentation was found so far.
+ llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs;
+
+ ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
+ ParamVarDocs.resize(ParamVars.size(), NULL);
+
+ // First pass over all \\param commands: resolve all parameter names.
+ for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
+ I != E; ++I) {
+ ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
+ if (!PCC || !PCC->hasParamName())
+ continue;
+ StringRef ParamName = PCC->getParamNameAsWritten();
+
+ // Check that referenced parameter name is in the function decl.
+ const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,
+ ParamVars);
+ if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) {
+ UnresolvedParamCommands.push_back(PCC);
+ continue;
+ }
+ PCC->setParamIndex(ResolvedParamIndex);
+ if (ParamVarDocs[ResolvedParamIndex]) {
+ SourceRange ArgRange = PCC->getParamNameRange();
+ Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)
+ << ParamName << ArgRange;
+ ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
+ Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
+ << PrevCommand->getParamNameRange();
+ }
+ ParamVarDocs[ResolvedParamIndex] = PCC;
+ }
+
+ // Find parameter declarations that have no corresponding \\param.
+ llvm::SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;
+ for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
+ if (!ParamVarDocs[i])
+ OrphanedParamDecls.push_back(ParamVars[i]);
+ }
+
+ // Second pass over unresolved \\param commands: do typo correction.
+ // Suggest corrections from a set of parameter declarations that have no
+ // corresponding \\param.
+ for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
+ const ParamCommandComment *PCC = UnresolvedParamCommands[i];
+
+ SourceRange ArgRange = PCC->getParamNameRange();
+ StringRef ParamName = PCC->getParamNameAsWritten();
+ Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)
+ << ParamName << ArgRange;
+
+ // All parameters documented -- can't suggest a correction.
+ if (OrphanedParamDecls.size() == 0)
+ continue;
+
+ unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
+ if (OrphanedParamDecls.size() == 1) {
+ // If one parameter is not documented then that parameter is the only
+ // possible suggestion.
+ CorrectedParamIndex = 0;
+ } else {
+ // Do typo correction.
+ CorrectedParamIndex = correctTypoInParmVarReference(ParamName,
+ OrphanedParamDecls);
+ }
+ if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
+ const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
+ if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
+ Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)
+ << CorrectedII->getName()
+ << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
+ }
+ }
}
bool Sema::isFunctionDecl() {
@@ -553,7 +661,6 @@ ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
void Sema::inspectThisDecl() {
ThisDeclInfo->fill();
- ParamVarDocs.resize(ThisDeclInfo->ParamVars.size(), NULL);
}
unsigned Sema::resolveParmVarReference(StringRef Name,
@@ -629,7 +736,7 @@ unsigned Sema::correctTypoInParmVarReference(
if (Corrector.getBestDecl())
return Corrector.getBestDeclIndex();
else
- return ParamCommandComment::InvalidParamIndex;;
+ return ParamCommandComment::InvalidParamIndex;
}
namespace {
@@ -700,7 +807,7 @@ StringRef Sema::correctTypoInTParamReference(
InlineCommandComment::RenderKind
Sema::getInlineCommandRenderKind(StringRef Name) const {
- assert(Traits.isInlineCommand(Name));
+ assert(Traits.getCommandInfo(Name)->IsInlineCommand);
return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
.Case("b", InlineCommandComment::RenderBold)
@@ -709,31 +816,6 @@ Sema::getInlineCommandRenderKind(StringRef Name) const {
.Default(InlineCommandComment::RenderNormal);
}
-bool Sema::isHTMLEndTagOptional(StringRef Name) {
- return llvm::StringSwitch<bool>(Name)
- .Case("p", true)
- .Case("li", true)
- .Case("dt", true)
- .Case("dd", true)
- .Case("tr", true)
- .Case("th", true)
- .Case("td", true)
- .Case("thead", true)
- .Case("tfoot", true)
- .Case("tbody", true)
- .Case("colgroup", true)
- .Default(false);
-}
-
-bool Sema::isHTMLEndTagForbidden(StringRef Name) {
- return llvm::StringSwitch<bool>(Name)
- .Case("br", true)
- .Case("hr", true)
- .Case("img", true)
- .Case("col", true)
- .Default(false);
-}
-
} // end namespace comments
} // end namespace clang
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d5b0be3..7b13755 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -126,12 +126,12 @@ static LinkageInfo getLVForTemplateArgumentList(const TemplateArgument *Args,
break;
case TemplateArgument::Declaration:
- // The decl can validly be null as the representation of nullptr
- // arguments, valid only in C++0x.
- if (Decl *D = Args[I].getAsDecl()) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
- LV.mergeWithMin(getLVForDecl(ND, OnlyTemplate));
- }
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(Args[I].getAsDecl()))
+ LV.mergeWithMin(getLVForDecl(ND, OnlyTemplate));
+ break;
+
+ case TemplateArgument::NullPtr:
+ LV.mergeWithMin(getLVForType(Args[I].getNullPtrType()));
break;
case TemplateArgument::Template:
@@ -193,7 +193,7 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) {
// anyway.
return TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition &&
- FD->hasBody(Def) && Def->isInlined();
+ FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
}
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
@@ -213,12 +213,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
if (Var->getStorageClass() == SC_Static)
return LinkageInfo::internal();
- // - an object or reference that is explicitly declared const
- // and neither explicitly declared extern nor previously
- // declared to have external linkage; or
- // (there is no equivalent in C99)
+ // - a non-volatile object or reference that is explicitly declared const
+ // or constexpr and neither explicitly declared extern nor previously
+ // declared to have external linkage; or (there is no equivalent in C99)
if (Context.getLangOpts().CPlusPlus &&
- Var->getType().isConstant(Context) &&
+ Var->getType().isConstQualified() &&
+ !Var->getType().isVolatileQualified() &&
Var->getStorageClass() != SC_Extern &&
Var->getStorageClass() != SC_PrivateExtern) {
bool FoundExtern = false;
@@ -236,8 +236,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
for (; PrevVar; PrevVar = PrevVar->getPreviousDecl())
if (PrevVar->getStorageClass() == SC_PrivateExtern)
break;
- if (PrevVar)
- return PrevVar->getLinkageAndVisibility();
+ if (PrevVar)
+ return PrevVar->getLinkageAndVisibility();
}
} else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
// C++ [temp]p4:
@@ -341,25 +341,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
if (Var->getStorageClass() == SC_PrivateExtern)
LV.mergeVisibility(HiddenVisibility, true);
- if (!Context.getLangOpts().CPlusPlus &&
- (Var->getStorageClass() == SC_Extern ||
- Var->getStorageClass() == SC_PrivateExtern)) {
-
- // C99 6.2.2p4:
- // For an identifier declared with the storage-class specifier
- // extern in a scope in which a prior declaration of that
- // identifier is visible, if the prior declaration specifies
- // internal or external linkage, the linkage of the identifier
- // at the later declaration is the same as the linkage
- // specified at the prior declaration. If no prior declaration
- // is visible, or if the prior declaration specifies no
- // linkage, then the identifier has external linkage.
- if (const VarDecl *PrevVar = Var->getPreviousDecl()) {
- LinkageInfo PrevLV = getLVForDecl(PrevVar, OnlyTemplate);
- if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
- LV.mergeVisibility(PrevLV);
- }
- }
+ // Note that Sema::MergeVarDecl already takes care of implementing
+ // C99 6.2.2p4 and propagating the visibility attribute, so we don't have
+ // to do it here.
// - a function, unless it has internal linkage; or
} else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
@@ -841,13 +825,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) {
if (llvm::Optional<Visibility> Vis = Var->getExplicitVisibility())
LV.mergeVisibility(*Vis, true);
}
-
- if (const VarDecl *Prev = Var->getPreviousDecl()) {
- LinkageInfo PrevLV = getLVForDecl(Prev, OnlyTemplate);
- if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
- LV.mergeVisibility(PrevLV);
- }
+ // Note that Sema::MergeVarDecl already takes care of implementing
+ // C99 6.2.2p4 and propagating the visibility attribute, so we don't
+ // have to do it here.
return LV;
}
}
@@ -903,7 +884,7 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
const FunctionProtoType *FT = 0;
if (FD->hasWrittenPrototype())
- FT = dyn_cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>());
+ FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>());
OS << *FD << '(';
if (FT) {
@@ -1204,8 +1185,11 @@ void VarDecl::setStorageClass(StorageClass SC) {
}
SourceRange VarDecl::getSourceRange() const {
- if (getInit())
- return SourceRange(getOuterLocStart(), getInit()->getLocEnd());
+ if (const Expr *Init = getInit()) {
+ SourceLocation InitEnd = Init->getLocEnd();
+ if (InitEnd.isValid())
+ return SourceRange(getOuterLocStart(), InitEnd);
+ }
return DeclaratorDecl::getSourceRange();
}
@@ -1859,7 +1843,7 @@ unsigned FunctionDecl::getBuiltinID() const {
/// based on its FunctionType. This is the length of the ParamInfo array
/// after it has been created.
unsigned FunctionDecl::getNumParams() const {
- const FunctionType *FT = getType()->getAs<FunctionType>();
+ const FunctionType *FT = getType()->castAs<FunctionType>();
if (isa<FunctionNoProtoType>(FT))
return 0;
return cast<FunctionProtoType>(FT)->getNumArgs();
@@ -2514,7 +2498,7 @@ unsigned FieldDecl::getFieldIndex() const {
unsigned Index = 0;
const RecordDecl *RD = getParent();
const FieldDecl *LastFD = 0;
- bool IsMsStruct = RD->hasAttr<MsStructAttr>();
+ bool IsMsStruct = RD->isMsStruct(getASTContext());
for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
I != E; ++I, ++Index) {
@@ -2762,6 +2746,17 @@ void RecordDecl::completeDefinition() {
TagDecl::completeDefinition();
}
+/// isMsStruct - Get whether or not this record uses ms_struct layout.
+/// 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;
+}
+
+static bool isFieldOrIndirectField(Decl::Kind K) {
+ return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
+}
+
void RecordDecl::LoadFieldsFromExternalStorage() const {
ExternalASTSource *Source = getASTContext().getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
@@ -2771,7 +2766,8 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
SmallVector<Decl*, 64> Decls;
LoadedFieldsFromExternalStorage = true;
- switch (Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls)) {
+ switch (Source->FindExternalLexicalDecls(this, isFieldOrIndirectField,
+ Decls)) {
case ELR_Success:
break;
@@ -2783,7 +2779,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
#ifndef NDEBUG
// Check that all decls we got were FieldDecls.
for (unsigned i=0, e=Decls.size(); i != e; ++i)
- assert(isa<FieldDecl>(Decls[i]));
+ assert(isa<FieldDecl>(Decls[i]) || isa<IndirectFieldDecl>(Decls[i]));
#endif
if (Decls.empty())
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index f9ce46d..4400d50 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -961,7 +961,7 @@ DeclContext::lookup_result
ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
ArrayRef<NamedDecl*> Decls) {
- ASTContext &Context = DC->getParentASTContext();;
+ ASTContext &Context = DC->getParentASTContext();
StoredDeclsMap *Map;
if (!(Map = DC->LookupPtr.getPointer()))
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 2f21e4c..82e630a 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -90,11 +90,12 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
}
CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
- SourceLocation Loc, bool Dependent) {
+ TypeSourceInfo *Info, SourceLocation Loc,
+ bool Dependent) {
CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc,
0, 0);
R->IsBeingDefined = true;
- R->DefinitionData = new (C) struct LambdaDefinitionData(R, Dependent);
+ R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent);
C.getTypeDeclType(R, /*PrevDecl=*/0);
return R;
}
@@ -239,10 +240,13 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// -- the constructor selected to copy/move each direct base class
// subobject is trivial, and
// FIXME: C++0x: We need to only consider the selected constructor
- // instead of all of them.
+ // instead of all of them. For now, we treat a move constructor as being
+ // non-trivial if it calls anything other than a trivial move constructor.
if (!BaseClassDecl->hasTrivialCopyConstructor())
data().HasTrivialCopyConstructor = false;
- if (!BaseClassDecl->hasTrivialMoveConstructor())
+ if (!BaseClassDecl->hasTrivialMoveConstructor() ||
+ !(BaseClassDecl->hasDeclaredMoveConstructor() ||
+ BaseClassDecl->needsImplicitMoveConstructor()))
data().HasTrivialMoveConstructor = false;
// C++0x [class.copy]p27:
@@ -254,7 +258,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// of all of them.
if (!BaseClassDecl->hasTrivialCopyAssignment())
data().HasTrivialCopyAssignment = false;
- if (!BaseClassDecl->hasTrivialMoveAssignment())
+ if (!BaseClassDecl->hasTrivialMoveAssignment() ||
+ !(BaseClassDecl->hasDeclaredMoveAssignment() ||
+ BaseClassDecl->needsImplicitMoveAssignment()))
data().HasTrivialMoveAssignment = false;
// C++11 [class.ctor]p6:
@@ -466,7 +472,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (!D->isImplicit() &&
!isa<FieldDecl>(D) &&
!isa<IndirectFieldDecl>(D) &&
- (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class))
+ (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class ||
+ cast<TagDecl>(D)->getTagKind() == TTK_Interface))
data().HasOnlyCMembers = false;
// Ignore friends and invalid declarations.
@@ -828,7 +835,9 @@ NotASpecialMember:;
// FIXME: C++0x: We don't correctly model 'selected' constructors.
if (!FieldRec->hasTrivialCopyConstructor())
data().HasTrivialCopyConstructor = false;
- if (!FieldRec->hasTrivialMoveConstructor())
+ if (!FieldRec->hasTrivialMoveConstructor() ||
+ !(FieldRec->hasDeclaredMoveConstructor() ||
+ FieldRec->needsImplicitMoveConstructor()))
data().HasTrivialMoveConstructor = false;
// C++0x [class.copy]p27:
@@ -840,7 +849,9 @@ NotASpecialMember:;
// FIXME: C++0x: We don't correctly model 'selected' operators.
if (!FieldRec->hasTrivialCopyAssignment())
data().HasTrivialCopyAssignment = false;
- if (!FieldRec->hasTrivialMoveAssignment())
+ if (!FieldRec->hasTrivialMoveAssignment() ||
+ !(FieldRec->hasDeclaredMoveAssignment() ||
+ FieldRec->needsImplicitMoveAssignment()))
data().HasTrivialMoveAssignment = false;
if (!FieldRec->hasTrivialDestructor())
@@ -936,7 +947,8 @@ NotASpecialMember:;
}
bool CXXRecordDecl::isCLike() const {
- if (getTagKind() == TTK_Class || !TemplateOrInstantiation.isNull())
+ if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
+ !TemplateOrInstantiation.isNull())
return false;
if (!hasDefinition())
return true;
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 4d48ad8..65a9878 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/ASTMutationListener.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -93,6 +94,16 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
return 0;
}
+IdentifierInfo *
+ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const {
+ SmallString<128> ivarName;
+ {
+ llvm::raw_svector_ostream os(ivarName);
+ os << '_' << getIdentifier()->getName();
+ }
+ return &Ctx.Idents.get(ivarName.str());
+}
+
/// FindPropertyDeclaration - Finds declaration of the property given its name
/// in 'PropertyId' and returns it. It returns 0, if not found.
ObjCPropertyDecl *
@@ -179,6 +190,21 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
return 0;
}
+void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM) const {
+ for (ObjCContainerDecl::prop_iterator P = prop_begin(),
+ E = prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = *P;
+ PM[Prop->getIdentifier()] = Prop;
+ }
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = all_referenced_protocol_begin(),
+ E = all_referenced_protocol_end(); PI != E; ++PI)
+ (*PI)->collectPropertiesToImplement(PM);
+ // Note, the properties declared only in class extensions are still copied
+ // into the main @interface's property list, and therefore we don't
+ // explicitly, have to search class extension properties.
+}
+
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
ASTContext &C)
@@ -414,16 +440,15 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
DeclContext *contextDecl,
bool isInstance,
bool isVariadic,
- bool isSynthesized,
+ bool isPropertyAccessor,
bool isImplicitlyDeclared,
bool isDefined,
ImplementationControl impControl,
bool HasRelatedResultType) {
return new (C) ObjCMethodDecl(beginLoc, endLoc,
SelInfo, T, ResultTInfo, contextDecl,
- isInstance,
- isVariadic, isSynthesized, isImplicitlyDeclared,
- isDefined,
+ isInstance, isVariadic, isPropertyAccessor,
+ isImplicitlyDeclared, isDefined,
impControl,
HasRelatedResultType);
}
@@ -434,6 +459,10 @@ ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
Selector(), QualType(), 0, 0);
}
+Stmt *ObjCMethodDecl::getBody() const {
+ return Body.get(getASTContext().getExternalSource());
+}
+
void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
assert(PrevMethod);
getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
@@ -707,6 +736,224 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
llvm_unreachable("unknown method context");
}
+static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
+ const ObjCMethodDecl *Method,
+ SmallVectorImpl<const ObjCMethodDecl *> &Methods,
+ bool MovedToSuper) {
+ if (!Container)
+ return;
+
+ // In categories look for overriden methods from protocols. A method from
+ // category is not "overriden" since it is considered as the "same" method
+ // (same USR) as the one from the interface.
+ if (const ObjCCategoryDecl *
+ Category = dyn_cast<ObjCCategoryDecl>(Container)) {
+ // Check whether we have a matching method at this category but only if we
+ // are at the super class level.
+ if (MovedToSuper)
+ if (ObjCMethodDecl *
+ Overridden = Container->getMethod(Method->getSelector(),
+ Method->isInstanceMethod()))
+ if (Method != Overridden) {
+ // We found an override at this category; there is no need to look
+ // into its protocols.
+ Methods.push_back(Overridden);
+ return;
+ }
+
+ for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
+ PEnd = Category->protocol_end();
+ P != PEnd; ++P)
+ CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper);
+ return;
+ }
+
+ // Check whether we have a matching method at this level.
+ if (const ObjCMethodDecl *
+ Overridden = Container->getMethod(Method->getSelector(),
+ Method->isInstanceMethod()))
+ if (Method != Overridden) {
+ // We found an override at this level; there is no need to look
+ // into other protocols or categories.
+ Methods.push_back(Overridden);
+ return;
+ }
+
+ if (const ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){
+ for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
+ PEnd = Protocol->protocol_end();
+ P != PEnd; ++P)
+ CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper);
+ }
+
+ if (const ObjCInterfaceDecl *
+ Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
+ for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(),
+ PEnd = Interface->protocol_end();
+ P != PEnd; ++P)
+ CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper);
+
+ for (const ObjCCategoryDecl *Category = Interface->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ CollectOverriddenMethodsRecurse(Category, Method, Methods,
+ MovedToSuper);
+
+ if (const ObjCInterfaceDecl *Super = Interface->getSuperClass())
+ return CollectOverriddenMethodsRecurse(Super, Method, Methods,
+ /*MovedToSuper=*/true);
+ }
+}
+
+static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container,
+ const ObjCMethodDecl *Method,
+ SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
+ CollectOverriddenMethodsRecurse(Container, Method, Methods,
+ /*MovedToSuper=*/false);
+}
+
+static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
+ SmallVectorImpl<const ObjCMethodDecl *> &overridden) {
+ assert(Method->isOverriding());
+
+ if (const ObjCProtocolDecl *
+ ProtD = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
+ CollectOverriddenMethods(ProtD, Method, overridden);
+
+ } else if (const ObjCImplDecl *
+ IMD = dyn_cast<ObjCImplDecl>(Method->getDeclContext())) {
+ const ObjCInterfaceDecl *ID = IMD->getClassInterface();
+ if (!ID)
+ return;
+ // Start searching for overridden methods using the method from the
+ // interface as starting point.
+ if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
+ Method->isInstanceMethod()))
+ Method = IFaceMeth;
+ CollectOverriddenMethods(ID, Method, overridden);
+
+ } else if (const ObjCCategoryDecl *
+ CatD = dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) {
+ const ObjCInterfaceDecl *ID = CatD->getClassInterface();
+ if (!ID)
+ return;
+ // Start searching for overridden methods using the method from the
+ // interface as starting point.
+ if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
+ Method->isInstanceMethod()))
+ Method = IFaceMeth;
+ CollectOverriddenMethods(ID, Method, overridden);
+
+ } else {
+ CollectOverriddenMethods(
+ dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()),
+ Method, overridden);
+ }
+}
+
+static void collectOnCategoriesAfterLocation(SourceLocation Loc,
+ const ObjCInterfaceDecl *Class,
+ SourceManager &SM,
+ const ObjCMethodDecl *Method,
+ SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
+ if (!Class)
+ return;
+
+ for (const ObjCCategoryDecl *Category = Class->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ if (SM.isBeforeInTranslationUnit(Loc, Category->getLocation()))
+ CollectOverriddenMethodsRecurse(Category, Method, Methods, true);
+
+ collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), SM,
+ Method, Methods);
+}
+
+/// \brief Faster collection that is enabled when ObjCMethodDecl::isOverriding()
+/// returns false.
+/// You'd think that in that case there are no overrides but categories can
+/// "introduce" new overridden methods that are missed by Sema because the
+/// overrides lookup that it does for methods, inside implementations, will
+/// stop at the interface level (if there is a method there) and not look
+/// further in super classes.
+/// Methods in an implementation can overide methods in super class's category
+/// but not in current class's category. But, such methods
+static void collectOverriddenMethodsFast(SourceManager &SM,
+ const ObjCMethodDecl *Method,
+ SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
+ assert(!Method->isOverriding());
+
+ const ObjCContainerDecl *
+ ContD = cast<ObjCContainerDecl>(Method->getDeclContext());
+ if (isa<ObjCInterfaceDecl>(ContD) || isa<ObjCProtocolDecl>(ContD))
+ return;
+ const ObjCInterfaceDecl *Class = Method->getClassInterface();
+ if (!Class)
+ return;
+
+ collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(),
+ SM, Method, Methods);
+}
+
+void ObjCMethodDecl::getOverriddenMethods(
+ SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const {
+ const ObjCMethodDecl *Method = this;
+
+ if (Method->isRedeclaration()) {
+ Method = cast<ObjCContainerDecl>(Method->getDeclContext())->
+ getMethod(Method->getSelector(), Method->isInstanceMethod());
+ }
+
+ if (!Method->isOverriding()) {
+ collectOverriddenMethodsFast(getASTContext().getSourceManager(),
+ Method, Overridden);
+ } else {
+ collectOverriddenMethodsSlow(Method, Overridden);
+ assert(!Overridden.empty() &&
+ "ObjCMethodDecl's overriding bit is not as expected");
+ }
+}
+
+const ObjCPropertyDecl *
+ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
+ Selector Sel = getSelector();
+ unsigned NumArgs = Sel.getNumArgs();
+ if (NumArgs > 1)
+ return 0;
+
+ if (!isInstanceMethod() || getMethodFamily() != OMF_None)
+ return 0;
+
+ if (isPropertyAccessor()) {
+ const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());
+ bool IsGetter = (NumArgs == 0);
+
+ for (ObjCContainerDecl::prop_iterator I = Container->prop_begin(),
+ E = Container->prop_end();
+ I != E; ++I) {
+ Selector NextSel = IsGetter ? (*I)->getGetterName()
+ : (*I)->getSetterName();
+ if (NextSel == Sel)
+ return *I;
+ }
+
+ llvm_unreachable("Marked as a property accessor but no property found!");
+ }
+
+ if (!CheckOverrides)
+ return 0;
+
+ typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy;
+ OverridesTy Overrides;
+ getOverriddenMethods(Overrides);
+ for (OverridesTy::const_iterator I = Overrides.begin(), E = Overrides.end();
+ I != E; ++I) {
+ if (const ObjCPropertyDecl *Prop = (*I)->findPropertyDecl(false))
+ return Prop;
+ }
+
+ return 0;
+
+}
+
//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
@@ -1081,6 +1328,20 @@ void ObjCProtocolDecl::startDefinition() {
RD->Data = this->Data;
}
+void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM) const {
+ for (ObjCProtocolDecl::prop_iterator P = prop_begin(),
+ E = prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = *P;
+ // Insert into PM if not there already.
+ PM.insert(std::make_pair(Prop->getIdentifier(), Prop));
+ }
+ // Scan through protocol's protocols.
+ for (ObjCProtocolDecl::protocol_iterator PI = protocol_begin(),
+ E = protocol_end(); PI != E; ++PI)
+ (*PI)->collectPropertiesToImplement(PM);
+}
+
+
//===----------------------------------------------------------------------===//
// ObjCCategoryDecl
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 7f47604..386ad66 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -105,6 +105,8 @@ static QualType GetBaseType(QualType T) {
break;
else if (const PointerType* PTy = BaseType->getAs<PointerType>())
BaseType = PTy->getPointeeType();
+ else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
+ BaseType = BPy->getPointeeType();
else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
BaseType = ATy->getElementType();
else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
@@ -189,6 +191,9 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
}
void DeclPrinter::prettyPrintAttributes(Decl *D) {
+ if (Policy.SuppressAttributes)
+ return;
+
if (D->hasAttrs()) {
AttrVec &Attrs = D->getAttrs();
for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
@@ -220,6 +225,9 @@ void DeclPrinter::Print(AccessSpecifier AS) {
//----------------------------------------------------------------------------
void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
+ if (Policy.TerseOutput)
+ return;
+
if (Indent)
Indentation += Policy.Indentation;
@@ -459,7 +467,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (I)
Proto += ", ";
- Proto += FT->getExceptionType(I).getAsString(SubPolicy);;
+ Proto += FT->getExceptionType(I).getAsString(SubPolicy);
}
Proto += ")";
} else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
@@ -550,7 +558,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Out << " = 0";
else if (D->isDeletedAsWritten())
Out << " = delete";
- else if (D->doesThisDeclarationHaveABody()) {
+ else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) {
if (!D->hasPrototype() && D->getNumParams()) {
// This is a K&R function definition, so we need to print the
// parameters.
@@ -621,13 +629,13 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
ImplicitInit = D->getInitStyle() == VarDecl::CallInit &&
Construct->getNumArgs() == 0 && !Construct->isListInitialization();
if (!ImplicitInit) {
- if (D->getInitStyle() == VarDecl::CallInit)
+ if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
Out << "(";
else if (D->getInitStyle() == VarDecl::CInit) {
Out << " = ";
}
Init->printPretty(Out, 0, Policy, Indentation);
- if (D->getInitStyle() == VarDecl::CallInit)
+ if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
Out << ")";
}
}
@@ -869,7 +877,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isVariadic())
Out << ", ...";
- if (OMD->getBody()) {
+ if (OMD->getBody() && !Policy.TerseOutput) {
Out << ' ';
OMD->getBody()->printPretty(Out, 0, Policy);
Out << '\n';
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index a7e8999..a70983f 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -32,9 +32,25 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
NamedDecl **Params, unsigned NumParams,
SourceLocation RAngleLoc)
: TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
- NumParams(NumParams) {
- for (unsigned Idx = 0; Idx < NumParams; ++Idx)
- begin()[Idx] = Params[Idx];
+ NumParams(NumParams), ContainsUnexpandedParameterPack(false) {
+ assert(this->NumParams == NumParams && "Too many template parameters");
+ for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
+ NamedDecl *P = Params[Idx];
+ begin()[Idx] = P;
+
+ if (!P->isTemplateParameterPack()) {
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
+ if (NTTP->getType()->containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
+
+ if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
+ if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
+
+ // FIXME: If a default argument contains an unexpanded parameter pack, the
+ // template parameter list does too.
+ }
+ }
}
TemplateParameterList *
@@ -577,6 +593,19 @@ SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
void TemplateTemplateParmDecl::anchor() { }
+TemplateTemplateParmDecl::TemplateTemplateParmDecl(
+ DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
+ IdentifierInfo *Id, TemplateParameterList *Params,
+ unsigned NumExpansions, TemplateParameterList * const *Expansions)
+ : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
+ TemplateParmPosition(D, P), DefaultArgument(),
+ DefaultArgumentWasInherited(false), ParameterPack(true),
+ ExpandedParameterPack(true), NumExpandedParams(NumExpansions) {
+ if (Expansions)
+ std::memcpy(reinterpret_cast<void*>(this + 1), Expansions,
+ sizeof(TemplateParameterList*) * NumExpandedParams);
+}
+
TemplateTemplateParmDecl *
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
@@ -587,12 +616,35 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
}
TemplateTemplateParmDecl *
+TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D, unsigned P,
+ IdentifierInfo *Id,
+ TemplateParameterList *Params,
+ llvm::ArrayRef<TemplateParameterList*> Expansions) {
+ void *Mem = C.Allocate(sizeof(TemplateTemplateParmDecl) +
+ sizeof(TemplateParameterList*) * Expansions.size());
+ return new (Mem) TemplateTemplateParmDecl(DC, L, D, P, Id, Params,
+ Expansions.size(),
+ Expansions.data());
+}
+
+TemplateTemplateParmDecl *
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTemplateParmDecl));
return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, false,
0, 0);
}
+TemplateTemplateParmDecl *
+TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumExpansions) {
+ unsigned Size = sizeof(TemplateTemplateParmDecl) +
+ sizeof(TemplateParameterList*) * NumExpansions;
+ void *Mem = AllocateDeserializedDecl(C, ID, Size);
+ return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, 0, 0,
+ NumExpansions, 0);
+}
+
//===----------------------------------------------------------------------===//
// TemplateArgumentList Implementation
//===----------------------------------------------------------------------===//
@@ -712,13 +764,27 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
SourceRange
ClassTemplateSpecializationDecl::getSourceRange() const {
if (ExplicitInfo) {
- SourceLocation Begin = getExternLoc();
- if (Begin.isInvalid())
- Begin = getTemplateKeywordLoc();
- SourceLocation End = getRBraceLoc();
- if (End.isInvalid())
- End = getTypeAsWritten()->getTypeLoc().getEndLoc();
- return SourceRange(Begin, End);
+ SourceLocation Begin = getTemplateKeywordLoc();
+ if (Begin.isValid()) {
+ // Here we have an explicit (partial) specialization or instantiation.
+ assert(getSpecializationKind() == TSK_ExplicitSpecialization ||
+ getSpecializationKind() == TSK_ExplicitInstantiationDeclaration ||
+ getSpecializationKind() == TSK_ExplicitInstantiationDefinition);
+ if (getExternLoc().isValid())
+ Begin = getExternLoc();
+ SourceLocation End = getRBraceLoc();
+ if (End.isInvalid())
+ End = getTypeAsWritten()->getTypeLoc().getEndLoc();
+ return SourceRange(Begin, End);
+ }
+ // An implicit instantiation of a class template partial specialization
+ // uses ExplicitInfo to record the TypeAsWritten, but the source
+ // locations should be retrieved from the instantiation pattern.
+ typedef ClassTemplatePartialSpecializationDecl CTPSDecl;
+ CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this));
+ CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
+ assert(inst_from != 0);
+ return inst_from->getSourceRange();
}
else {
// No explicit info available.
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index 84f3fc4..5f43fbc 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -1,4 +1,4 @@
-//===--- DumpXML.cpp - Detailed XML dumping ---------------------*- C++ -*-===//
+//===--- DumpXML.cpp - Detailed XML dumping -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -64,6 +64,8 @@ template <class Impl> struct XMLDeclVisitor {
static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
void dispatch(Decl *D) {
+ if (D->isUsed())
+ static_cast<Impl*>(this)->set("used", "1");
switch (D->getKind()) {
#define DECL(DERIVED, BASE) \
case Decl::DERIVED: \
@@ -316,12 +318,12 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::NullPtr:
// FIXME: Implement!
break;
case TemplateArgument::Declaration: {
- if (Decl *D = A.getAsDecl())
- visitDeclRef(D);
+ visitDeclRef(A.getAsDecl());
break;
}
case TemplateArgument::Integral: {
@@ -841,7 +843,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
setFlag("instance", D->isInstanceMethod());
setFlag("variadic", D->isVariadic());
- setFlag("synthesized", D->isSynthesized());
+ setFlag("property_accessor", D->isPropertyAccessor());
setFlag("defined", D->isDefined());
setFlag("related_result_type", D->hasRelatedResultType());
}
@@ -920,6 +922,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
case CC_X86Pascal: return set("cc", "x86_pascal");
case CC_AAPCS: return set("cc", "aapcs");
case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
+ case CC_PnaclCall: return set("cc", "pnaclcall");
}
}
@@ -974,6 +977,16 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
setFlag("const", T->isConst());
setFlag("volatile", T->isVolatile());
setFlag("restrict", T->isRestrict());
+ switch (T->getExceptionSpecType()) {
+ case EST_None: break;
+ case EST_DynamicNone: set("exception_spec", "throw()"); break;
+ case EST_Dynamic: set("exception_spec", "throw(T)"); break;
+ case EST_MSAny: set("exception_spec", "throw(...)"); break;
+ case EST_BasicNoexcept: set("exception_spec", "noexcept"); break;
+ case EST_ComputedNoexcept: set("exception_spec", "noexcept(expr)"); break;
+ case EST_Unevaluated: set("exception_spec", "unevaluated"); break;
+ case EST_Uninstantiated: set("exception_spec", "uninstantiated"); break;
+ }
}
void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
push("parameters");
@@ -1023,7 +1036,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
void Decl::dumpXML() const {
- dump(llvm::errs());
+ dumpXML(llvm::errs());
}
void Decl::dumpXML(raw_ostream &out) const {
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 24361ef..f3a2e05 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -48,6 +48,75 @@ const CXXRecordDecl *Expr::getBestDynamicClassType() const {
return cast<CXXRecordDecl>(D);
}
+const Expr *
+Expr::skipRValueSubobjectAdjustments(
+ SmallVectorImpl<SubobjectAdjustment> &Adjustments) const {
+ const Expr *E = this;
+ while (true) {
+ E = E->IgnoreParens();
+
+ if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if ((CE->getCastKind() == CK_DerivedToBase ||
+ CE->getCastKind() == CK_UncheckedDerivedToBase) &&
+ E->getType()->isRecordType()) {
+ E = CE->getSubExpr();
+ CXXRecordDecl *Derived
+ = cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
+ Adjustments.push_back(SubobjectAdjustment(CE, Derived));
+ continue;
+ }
+
+ if (CE->getCastKind() == CK_NoOp) {
+ E = CE->getSubExpr();
+ continue;
+ }
+ } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ if (!ME->isArrow() && ME->getBase()->isRValue()) {
+ assert(ME->getBase()->getType()->isRecordType());
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
+ E = ME->getBase();
+ Adjustments.push_back(SubobjectAdjustment(Field));
+ continue;
+ }
+ }
+ } else if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->isPtrMemOp()) {
+ assert(BO->getRHS()->isRValue());
+ E = BO->getLHS();
+ const MemberPointerType *MPT =
+ BO->getRHS()->getType()->getAs<MemberPointerType>();
+ Adjustments.push_back(SubobjectAdjustment(MPT, BO->getRHS()));
+ }
+ }
+
+ // Nothing changed.
+ break;
+ }
+ return E;
+}
+
+const Expr *
+Expr::findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const {
+ const Expr *E = this;
+ // Look through single-element init lists that claim to be lvalues. They're
+ // just syntactic wrappers in this case.
+ if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) {
+ if (ILE->getNumInits() == 1 && ILE->isGLValue())
+ E = ILE->getInit(0);
+ }
+
+ // Look through expressions for materialized temporaries (for now).
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ MTE = M;
+ E = M->GetTemporaryExpr();
+ }
+
+ if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E))
+ E = DAE->getExpr();
+ return E;
+}
+
/// isKnownToHaveBooleanValue - Return true if this is an integer expression
/// that is known to return 0 or 1. This happens for _Bool/bool expressions
/// but also int expressions which are produced by things like comparisons in
@@ -784,19 +853,19 @@ void StringLiteral::setString(ASTContext &C, StringRef Str,
switch(CharByteWidth) {
case 1: {
char *AStrData = new (C) char[Length];
- std::memcpy(AStrData,Str.data(),Str.size());
+ std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
StrData.asChar = AStrData;
break;
}
case 2: {
uint16_t *AStrData = new (C) uint16_t[Length];
- std::memcpy(AStrData,Str.data(),Str.size());
+ std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
StrData.asUInt16 = AStrData;
break;
}
case 4: {
uint32_t *AStrData = new (C) uint32_t[Length];
- std::memcpy(AStrData,Str.data(),Str.size());
+ std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
StrData.asUInt32 = AStrData;
break;
}
@@ -869,7 +938,7 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++".
-const char *UnaryOperator::getOpcodeStr(Opcode Op) {
+StringRef UnaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
case UO_PostInc: return "++";
case UO_PostDec: return "--";
@@ -923,18 +992,18 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
//===----------------------------------------------------------------------===//
CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
- Expr **args, unsigned numargs, QualType t, ExprValueKind VK,
+ ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
SourceLocation rparenloc)
: Expr(SC, t, VK, OK_Ordinary,
fn->isTypeDependent(),
fn->isValueDependent(),
fn->isInstantiationDependent(),
fn->containsUnexpandedParameterPack()),
- NumArgs(numargs) {
+ NumArgs(args.size()) {
- SubExprs = new (C) Stmt*[numargs+PREARGS_START+NumPreArgs];
+ SubExprs = new (C) Stmt*[args.size()+PREARGS_START+NumPreArgs];
SubExprs[FN] = fn;
- for (unsigned i = 0; i != numargs; ++i) {
+ for (unsigned i = 0; i != args.size(); ++i) {
if (args[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
@@ -951,18 +1020,18 @@ CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
RParenLoc = rparenloc;
}
-CallExpr::CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs,
+CallExpr::CallExpr(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(numargs) {
+ NumArgs(args.size()) {
- SubExprs = new (C) Stmt*[numargs+PREARGS_START];
+ SubExprs = new (C) Stmt*[args.size()+PREARGS_START];
SubExprs[FN] = fn;
- for (unsigned i = 0; i != numargs; ++i) {
+ for (unsigned i = 0; i != args.size(); ++i) {
if (args[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
@@ -1123,15 +1192,15 @@ SourceLocation CallExpr::getLocEnd() const {
OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type,
SourceLocation OperatorLoc,
TypeSourceInfo *tsi,
- OffsetOfNode* compsPtr, unsigned numComps,
- Expr** exprsPtr, unsigned numExprs,
+ ArrayRef<OffsetOfNode> comps,
+ ArrayRef<Expr*> exprs,
SourceLocation RParenLoc) {
void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
- sizeof(OffsetOfNode) * numComps +
- sizeof(Expr*) * numExprs);
+ sizeof(OffsetOfNode) * comps.size() +
+ sizeof(Expr*) * exprs.size());
- return new (Mem) OffsetOfExpr(C, type, OperatorLoc, tsi, compsPtr, numComps,
- exprsPtr, numExprs, RParenLoc);
+ return new (Mem) OffsetOfExpr(C, type, OperatorLoc, tsi, comps, exprs,
+ RParenLoc);
}
OffsetOfExpr *OffsetOfExpr::CreateEmpty(ASTContext &C,
@@ -1144,8 +1213,7 @@ OffsetOfExpr *OffsetOfExpr::CreateEmpty(ASTContext &C,
OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
- OffsetOfNode* compsPtr, unsigned numComps,
- Expr** exprsPtr, unsigned numExprs,
+ ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
SourceLocation RParenLoc)
: Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary,
/*TypeDependent=*/false,
@@ -1153,19 +1221,19 @@ OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type,
tsi->getType()->isInstantiationDependentType(),
tsi->getType()->containsUnexpandedParameterPack()),
OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi),
- NumComps(numComps), NumExprs(numExprs)
+ NumComps(comps.size()), NumExprs(exprs.size())
{
- for(unsigned i = 0; i < numComps; ++i) {
- setComponent(i, compsPtr[i]);
+ for (unsigned i = 0; i != comps.size(); ++i) {
+ setComponent(i, comps[i]);
}
- for(unsigned i = 0; i < numExprs; ++i) {
- if (exprsPtr[i]->isTypeDependent() || exprsPtr[i]->isValueDependent())
+ for (unsigned i = 0; i != exprs.size(); ++i) {
+ if (exprs[i]->isTypeDependent() || exprs[i]->isValueDependent())
ExprBits.ValueDependent = true;
- if (exprsPtr[i]->containsUnexpandedParameterPack())
+ if (exprs[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
- setIndexExpr(i, exprsPtr[i]);
+ setIndexExpr(i, exprs[i]);
}
}
@@ -1259,9 +1327,12 @@ SourceLocation MemberExpr::getLocStart() const {
return MemberLoc;
}
SourceLocation MemberExpr::getLocEnd() const {
+ SourceLocation EndLoc = getMemberNameInfo().getEndLoc();
if (hasExplicitTemplateArgs())
- return getRAngleLoc();
- return getMemberNameInfo().getEndLoc();
+ EndLoc = getRAngleLoc();
+ else if (EndLoc.isInvalid())
+ EndLoc = getBase()->getLocEnd();
+ return EndLoc;
}
void CastExpr::CheckCastConsistency() const {
@@ -1311,12 +1382,16 @@ void CastExpr::CheckCastConsistency() const {
assert(getType()->isBlockPointerType());
assert(getSubExpr()->getType()->isBlockPointerType());
goto CheckNoBasePath;
-
+
+ case CK_FunctionToPointerDecay:
+ assert(getType()->isPointerType());
+ assert(getSubExpr()->getType()->isFunctionType());
+ goto CheckNoBasePath;
+
// These should not have an inheritance path.
case CK_Dynamic:
case CK_ToUnion:
case CK_ArrayToPointerDecay:
- case CK_FunctionToPointerDecay:
case CK_NullToMemberPointer:
case CK_NullToPointer:
case CK_ConstructorConversion:
@@ -1357,6 +1432,7 @@ void CastExpr::CheckCastConsistency() const {
case CK_IntegralComplexToBoolean:
case CK_LValueBitCast: // -> bool&
case CK_UserDefinedConversion: // operator bool()
+ case CK_BuiltinFnToFnPtr:
CheckNoBasePath:
assert(path_empty() && "Cast kind should not have a base path!");
break;
@@ -1469,6 +1545,8 @@ const char *CastExpr::getCastKindName() const {
return "NonAtomicToAtomic";
case CK_CopyAndAutoreleaseBlockObject:
return "CopyAndAutoreleaseBlockObject";
+ case CK_BuiltinFnToFnPtr:
+ return "BuiltinFnToFnPtr";
}
llvm_unreachable("Unhandled cast kind!");
@@ -1564,7 +1642,7 @@ CStyleCastExpr *CStyleCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
-const char *BinaryOperator::getOpcodeStr(Opcode Op) {
+StringRef BinaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
case BO_PtrMemD: return ".*";
case BO_PtrMemI: return "->*";
@@ -1666,16 +1744,15 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
}
InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc,
- Expr **initExprs, unsigned numInits,
- SourceLocation rbraceloc)
+ ArrayRef<Expr*> initExprs, SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
false, false),
- InitExprs(C, numInits),
- LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0)
+ InitExprs(C, initExprs.size()),
+ LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(0, true)
{
sawArrayRangeDesignator(false);
setInitializesStdInitializerList(false);
- for (unsigned I = 0; I != numInits; ++I) {
+ for (unsigned I = 0; I != initExprs.size(); ++I) {
if (initExprs[I]->isTypeDependent())
ExprBits.TypeDependent = true;
if (initExprs[I]->isValueDependent())
@@ -1686,7 +1763,7 @@ InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc,
ExprBits.ContainsUnexpandedParameterPack = true;
}
- InitExprs.insert(C, InitExprs.end(), initExprs, initExprs+numInits);
+ InitExprs.insert(C, InitExprs.end(), initExprs.begin(), initExprs.end());
}
void InitListExpr::reserveInits(ASTContext &C, unsigned NumInits) {
@@ -1723,15 +1800,15 @@ void InitListExpr::setArrayFiller(Expr *filler) {
bool InitListExpr::isStringLiteralInit() const {
if (getNumInits() != 1)
return false;
- const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(getType());
- if (!CAT || !CAT->getElementType()->isIntegerType())
+ const ArrayType *AT = getType()->getAsArrayTypeUnsafe();
+ if (!AT || !AT->getElementType()->isIntegerType())
return false;
- const Expr *Init = getInit(0)->IgnoreParenImpCasts();
+ const Expr *Init = getInit(0)->IgnoreParens();
return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);
}
SourceRange InitListExpr::getSourceRange() const {
- if (SyntacticForm)
+ if (InitListExpr *SyntacticForm = getSyntacticForm())
return SyntacticForm->getSourceRange();
SourceLocation Beg = LBraceLoc, End = RBraceLoc;
if (Beg.isInvalid()) {
@@ -1945,6 +2022,11 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
return false;
}
+ // If we don't know precisely what we're looking at, let's not warn.
+ case UnresolvedLookupExprClass:
+ case CXXUnresolvedConstructExprClass:
+ return false;
+
case CXXTemporaryObjectExprClass:
case CXXConstructExprClass:
return false;
@@ -2014,6 +2096,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
R1 = getSourceRange();
return true;
}
+ case CXXFunctionalCastExprClass:
case CStyleCastExprClass: {
// Ignore an explicit cast to void unless the operand is a non-trivial
// volatile lvalue.
@@ -2032,6 +2115,10 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
return false;
}
+ // Ignore casts within macro expansions.
+ if (getExprLoc().isMacroID())
+ return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
+
// If this is a cast to a constructor conversion, check the operand.
// Otherwise, the result of the cast is unused.
if (CE->getCastKind() == CK_ConstructorConversion)
@@ -2641,6 +2728,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
case UnresolvedMemberExprClass:
case PackExpansionExprClass:
case SubstNonTypeTemplateParmPackExprClass:
+ case FunctionParmPackExprClass:
llvm_unreachable("shouldn't see dependent / unresolved nodes here");
case DeclRefExprClass:
@@ -2995,6 +3083,24 @@ const ObjCPropertyRefExpr *Expr::getObjCProperty() const {
return cast<ObjCPropertyRefExpr>(E);
}
+bool Expr::isObjCSelfExpr() const {
+ const Expr *E = IgnoreParenImpCasts();
+
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+ if (!DRE)
+ return false;
+
+ const ImplicitParamDecl *Param = dyn_cast<ImplicitParamDecl>(DRE->getDecl());
+ if (!Param)
+ return false;
+
+ const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(Param->getDeclContext());
+ if (!M)
+ return false;
+
+ return M->getSelfDecl() == Param;
+}
+
FieldDecl *Expr::getBitField() {
Expr *E = this->IgnoreParens();
@@ -3339,33 +3445,29 @@ Selector ObjCMessageExpr::getSelector() const {
return Selector(SelectorOrMethod);
}
-ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
+QualType ObjCMessageExpr::getReceiverType() const {
switch (getReceiverKind()) {
case Instance:
- if (const ObjCObjectPointerType *Ptr
- = getInstanceReceiver()->getType()->getAs<ObjCObjectPointerType>())
- return Ptr->getInterfaceDecl();
- break;
-
+ return getInstanceReceiver()->getType();
case Class:
- if (const ObjCObjectType *Ty
- = getClassReceiver()->getAs<ObjCObjectType>())
- return Ty->getInterface();
- break;
-
+ return getClassReceiver();
case SuperInstance:
- if (const ObjCObjectPointerType *Ptr
- = getSuperType()->getAs<ObjCObjectPointerType>())
- return Ptr->getInterfaceDecl();
- break;
-
case SuperClass:
- if (const ObjCObjectType *Iface
- = getSuperType()->getAs<ObjCObjectType>())
- return Iface->getInterface();
- break;
+ return getSuperType();
}
+ llvm_unreachable("unexpected receiver kind");
+}
+
+ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
+ QualType T = getReceiverType();
+
+ if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
+ return Ptr->getInterfaceDecl();
+
+ if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>())
+ return Ty->getInterface();
+
return 0;
}
@@ -3386,17 +3488,17 @@ bool ChooseExpr::isConditionTrue(const ASTContext &C) const {
return getCond()->EvaluateKnownConstInt(C) != 0;
}
-ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
+ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, ArrayRef<Expr*> args,
QualType Type, SourceLocation BLoc,
SourceLocation RP)
: Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary,
Type->isDependentType(), Type->isDependentType(),
Type->isInstantiationDependentType(),
Type->containsUnexpandedParameterPack()),
- BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr)
+ BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size())
{
- SubExprs = new (C) Stmt*[nexpr];
- for (unsigned i = 0; i < nexpr; i++) {
+ SubExprs = new (C) Stmt*[args.size()];
+ for (unsigned i = 0; i != args.size(); i++) {
if (args[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
@@ -3421,8 +3523,9 @@ void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs,
GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
SourceLocation GenericLoc, Expr *ControllingExpr,
- TypeSourceInfo **AssocTypes, Expr **AssocExprs,
- unsigned NumAssocs, SourceLocation DefaultLoc,
+ ArrayRef<TypeSourceInfo*> AssocTypes,
+ ArrayRef<Expr*> AssocExprs,
+ SourceLocation DefaultLoc,
SourceLocation RParenLoc,
bool ContainsUnexpandedParameterPack,
unsigned ResultIndex)
@@ -3434,19 +3537,21 @@ GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
AssocExprs[ResultIndex]->isValueDependent(),
AssocExprs[ResultIndex]->isInstantiationDependent(),
ContainsUnexpandedParameterPack),
- AssocTypes(new (Context) TypeSourceInfo*[NumAssocs]),
- SubExprs(new (Context) Stmt*[END_EXPR+NumAssocs]), NumAssocs(NumAssocs),
- ResultIndex(ResultIndex), GenericLoc(GenericLoc), DefaultLoc(DefaultLoc),
- RParenLoc(RParenLoc) {
+ AssocTypes(new (Context) TypeSourceInfo*[AssocTypes.size()]),
+ SubExprs(new (Context) Stmt*[END_EXPR+AssocExprs.size()]),
+ NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex),
+ GenericLoc(GenericLoc), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) {
SubExprs[CONTROLLING] = ControllingExpr;
- std::copy(AssocTypes, AssocTypes+NumAssocs, this->AssocTypes);
- std::copy(AssocExprs, AssocExprs+NumAssocs, SubExprs+END_EXPR);
+ assert(AssocTypes.size() == AssocExprs.size());
+ std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes);
+ std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR);
}
GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
SourceLocation GenericLoc, Expr *ControllingExpr,
- TypeSourceInfo **AssocTypes, Expr **AssocExprs,
- unsigned NumAssocs, SourceLocation DefaultLoc,
+ ArrayRef<TypeSourceInfo*> AssocTypes,
+ ArrayRef<Expr*> AssocExprs,
+ SourceLocation DefaultLoc,
SourceLocation RParenLoc,
bool ContainsUnexpandedParameterPack)
: Expr(GenericSelectionExprClass,
@@ -3457,13 +3562,14 @@ GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context,
/*isValueDependent=*/true,
/*isInstantiationDependent=*/true,
ContainsUnexpandedParameterPack),
- AssocTypes(new (Context) TypeSourceInfo*[NumAssocs]),
- SubExprs(new (Context) Stmt*[END_EXPR+NumAssocs]), NumAssocs(NumAssocs),
- ResultIndex(-1U), GenericLoc(GenericLoc), DefaultLoc(DefaultLoc),
- RParenLoc(RParenLoc) {
+ AssocTypes(new (Context) TypeSourceInfo*[AssocTypes.size()]),
+ SubExprs(new (Context) Stmt*[END_EXPR+AssocExprs.size()]),
+ NumAssocs(AssocExprs.size()), ResultIndex(-1U), GenericLoc(GenericLoc),
+ DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) {
SubExprs[CONTROLLING] = ControllingExpr;
- std::copy(AssocTypes, AssocTypes+NumAssocs, this->AssocTypes);
- std::copy(AssocExprs, AssocExprs+NumAssocs, SubExprs+END_EXPR);
+ assert(AssocTypes.size() == AssocExprs.size());
+ std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes);
+ std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR);
}
//===----------------------------------------------------------------------===//
@@ -3483,8 +3589,7 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
const Designator *Designators,
SourceLocation EqualOrColonLoc,
bool GNUSyntax,
- Expr **IndexExprs,
- unsigned NumIndexExprs,
+ ArrayRef<Expr*> IndexExprs,
Expr *Init)
: Expr(DesignatedInitExprClass, Ty,
Init->getValueKind(), Init->getObjectKind(),
@@ -3492,7 +3597,7 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
Init->isInstantiationDependent(),
Init->containsUnexpandedParameterPack()),
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
- NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) {
+ NumDesignators(NumDesignators), NumSubExprs(IndexExprs.size() + 1) {
this->Designators = new (C) Designator[NumDesignators];
// Record the initializer itself.
@@ -3542,20 +3647,20 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
}
}
- assert(IndexIdx == NumIndexExprs && "Wrong number of index expressions");
+ assert(IndexIdx == IndexExprs.size() && "Wrong number of index expressions");
}
DesignatedInitExpr *
DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
unsigned NumDesignators,
- Expr **IndexExprs, unsigned NumIndexExprs,
+ ArrayRef<Expr*> IndexExprs,
SourceLocation ColonOrEqualLoc,
bool UsesColonSyntax, Expr *Init) {
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
- sizeof(Stmt *) * (NumIndexExprs + 1), 8);
+ sizeof(Stmt *) * (IndexExprs.size() + 1), 8);
return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators,
ColonOrEqualLoc, UsesColonSyntax,
- IndexExprs, NumIndexExprs, Init);
+ IndexExprs, Init);
}
DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
@@ -3651,13 +3756,13 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
}
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
- Expr **exprs, unsigned nexprs,
+ ArrayRef<Expr*> exprs,
SourceLocation rparenloc)
: Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary,
false, false, false, false),
- NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) {
- Exprs = new (C) Stmt*[nexprs];
- for (unsigned i = 0; i != nexprs; ++i) {
+ NumExprs(exprs.size()), LParenLoc(lparenloc), RParenLoc(rparenloc) {
+ Exprs = new (C) Stmt*[exprs.size()];
+ for (unsigned i = 0; i != exprs.size(); ++i) {
if (exprs[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (exprs[i]->isValueDependent())
@@ -3902,14 +4007,14 @@ ObjCSubscriptRefExpr *ObjCSubscriptRefExpr::Create(ASTContext &C,
getMethod, setMethod, RB);
}
-AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr,
+AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args,
QualType t, AtomicOp op, SourceLocation RP)
: Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary,
false, false, false, false),
- NumSubExprs(nexpr), BuiltinLoc(BLoc), RParenLoc(RP), Op(op)
+ NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op)
{
- assert(nexpr == getNumSubExprs(op) && "wrong number of subexpressions");
- for (unsigned i = 0; i < nexpr; i++) {
+ assert(args.size() == getNumSubExprs(op) && "wrong number of subexpressions");
+ for (unsigned i = 0; i != args.size(); i++) {
if (args[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 3fa49e0..55722a2 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -51,6 +51,26 @@ QualType CXXUuidofExpr::getTypeOperand() const {
.getUnqualifiedType();
}
+// static
+UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT) {
+ // Optionally remove one level of pointer, reference or array indirection.
+ const Type *Ty = QT.getTypePtr();
+ if (QT->isPointerType() || QT->isReferenceType())
+ Ty = QT->getPointeeType().getTypePtr();
+ else if (QT->isArrayType())
+ Ty = cast<ArrayType>(QT)->getElementType().getTypePtr();
+
+ // Loop all record redeclaration looking for an uuid attribute.
+ CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
+ E = RD->redecls_end(); I != E; ++I) {
+ if (UuidAttr *Uuid = I->getAttr<UuidAttr>())
+ return Uuid;
+ }
+
+ return 0;
+}
+
// CXXScalarValueInitExpr
SourceRange CXXScalarValueInitExpr::getSourceRange() const {
SourceLocation Start = RParenLoc;
@@ -63,24 +83,24 @@ SourceRange CXXScalarValueInitExpr::getSourceRange() const {
CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
FunctionDecl *operatorDelete,
bool usualArrayDeleteWantsSize,
- Expr **placementArgs, unsigned numPlaceArgs,
+ ArrayRef<Expr*> placementArgs,
SourceRange typeIdParens, Expr *arraySize,
InitializationStyle initializationStyle,
Expr *initializer, QualType ty,
TypeSourceInfo *allocatedTypeInfo,
- SourceLocation startLoc, SourceRange directInitRange)
+ SourceRange Range, SourceRange directInitRange)
: Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary,
ty->isDependentType(), ty->isDependentType(),
ty->isInstantiationDependentType(),
ty->containsUnexpandedParameterPack()),
SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete),
AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
- StartLoc(startLoc), DirectInitRange(directInitRange),
+ Range(Range), DirectInitRange(directInitRange),
GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
assert((initializer != 0 || initializationStyle == NoInit) &&
"Only NoInit can have no initializer.");
StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;
- AllocateArgsArray(C, arraySize != 0, numPlaceArgs, initializer != 0);
+ AllocateArgsArray(C, arraySize != 0, placementArgs.size(), initializer != 0);
unsigned i = 0;
if (Array) {
if (arraySize->isInstantiationDependent())
@@ -102,7 +122,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
SubExprs[i++] = initializer;
}
- for (unsigned j = 0; j < NumPlacementArgs; ++j) {
+ for (unsigned j = 0; j != placementArgs.size(); ++j) {
if (placementArgs[j]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (placementArgs[j]->containsUnexpandedParameterPack())
@@ -110,6 +130,14 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
SubExprs[i++] = placementArgs[j];
}
+
+ switch (getInitializationStyle()) {
+ case CallInit:
+ this->Range.setEnd(DirectInitRange.getEnd()); break;
+ case ListInit:
+ this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); break;
+ default: break;
+ }
}
void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray,
@@ -127,18 +155,6 @@ bool CXXNewExpr::shouldNullCheckAllocation(ASTContext &Ctx) const {
castAs<FunctionProtoType>()->isNothrow(Ctx);
}
-SourceLocation CXXNewExpr::getEndLoc() const {
- switch (getInitializationStyle()) {
- case NoInit:
- return AllocatedTypeInfo->getTypeLoc().getEndLoc();
- case CallInit:
- return DirectInitRange.getEnd();
- case ListInit:
- return getInitializer()->getSourceRange().getEnd();
- }
- llvm_unreachable("bogus initialization style");
-}
-
// CXXDeleteExpr
QualType CXXDeleteExpr::getDestroyedType() const {
const Expr *Arg = getArgument();
@@ -227,7 +243,7 @@ UnresolvedLookupExpr::Create(ASTContext &C,
return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
TemplateKWLoc, NameInfo,
ADL, /*Overload*/ true, Args,
- Begin, End, /*StdIsAssociated=*/false);
+ Begin, End);
}
UnresolvedLookupExpr *
@@ -697,15 +713,14 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C,
CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
CXXConstructorDecl *Cons,
TypeSourceInfo *Type,
- Expr **Args,
- unsigned NumArgs,
+ ArrayRef<Expr*> Args,
SourceRange parenRange,
bool HadMultipleCandidates,
bool ZeroInitialization)
: CXXConstructExpr(C, CXXTemporaryObjectExprClass,
Type->getType().getNonReferenceType(),
Type->getTypeLoc().getBeginLoc(),
- Cons, false, Args, NumArgs,
+ Cons, false, Args,
HadMultipleCandidates, /*FIXME*/false, ZeroInitialization,
CXXConstructExpr::CK_Complete, parenRange),
Type(Type) {
@@ -719,14 +734,14 @@ SourceRange CXXTemporaryObjectExpr::getSourceRange() const {
CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr*> Args,
bool HadMultipleCandidates,
bool ListInitialization,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenRange) {
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D,
- Elidable, Args, NumArgs,
+ Elidable, Args,
HadMultipleCandidates, ListInitialization,
ZeroInitialization, ConstructKind,
ParenRange);
@@ -735,7 +750,7 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T,
CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool elidable,
- Expr **args, unsigned numargs,
+ ArrayRef<Expr*> args,
bool HadMultipleCandidates,
bool ListInitialization,
bool ZeroInitialization,
@@ -745,16 +760,16 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
T->isDependentType(), T->isDependentType(),
T->isInstantiationDependentType(),
T->containsUnexpandedParameterPack()),
- Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs),
+ Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(args.size()),
Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates),
ListInitialization(ListInitialization),
ZeroInitialization(ZeroInitialization),
ConstructKind(ConstructKind), Args(0)
{
if (NumArgs) {
- Args = new (C) Stmt*[NumArgs];
+ Args = new (C) Stmt*[args.size()];
- for (unsigned i = 0; i != NumArgs; ++i) {
+ for (unsigned i = 0; i != args.size(); ++i) {
assert(args[i] && "NULL argument in CXXConstructExpr");
if (args[i]->isValueDependent())
@@ -877,9 +892,12 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
QualType T = Context.getTypeDeclType(Class);
unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (Captures.size() + 1);
- if (!ArrayIndexVars.empty())
- Size += sizeof(VarDecl *) * ArrayIndexVars.size()
- + sizeof(unsigned) * (Captures.size() + 1);
+ if (!ArrayIndexVars.empty()) {
+ Size += sizeof(unsigned) * (Captures.size() + 1);
+ // Realign for following VarDecl array.
+ Size = llvm::RoundUpToAlignment(Size, llvm::alignOf<VarDecl*>());
+ Size += sizeof(VarDecl *) * ArrayIndexVars.size();
+ }
void *Mem = Context.Allocate(Size);
return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault,
Captures, ExplicitParams, ExplicitResultType,
@@ -997,8 +1015,7 @@ ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, EmptyShell empty,
CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
SourceLocation LParenLoc,
- Expr **Args,
- unsigned NumArgs,
+ ArrayRef<Expr*> Args,
SourceLocation RParenLoc)
: Expr(CXXUnresolvedConstructExprClass,
Type->getType().getNonReferenceType(),
@@ -1011,9 +1028,9 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
Type(Type),
LParenLoc(LParenLoc),
RParenLoc(RParenLoc),
- NumArgs(NumArgs) {
+ NumArgs(Args.size()) {
Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1);
- for (unsigned I = 0; I != NumArgs; ++I) {
+ for (unsigned I = 0; I != Args.size(); ++I) {
if (Args[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -1025,13 +1042,11 @@ CXXUnresolvedConstructExpr *
CXXUnresolvedConstructExpr::Create(ASTContext &C,
TypeSourceInfo *Type,
SourceLocation LParenLoc,
- Expr **Args,
- unsigned NumArgs,
+ ArrayRef<Expr*> Args,
SourceLocation RParenLoc) {
void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) +
- sizeof(Expr *) * NumArgs);
- return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc,
- Args, NumArgs, RParenLoc);
+ sizeof(Expr *) * Args.size());
+ return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc, Args, RParenLoc);
}
CXXUnresolvedConstructExpr *
@@ -1300,6 +1315,34 @@ TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
return TemplateArgument(Arguments, NumArguments);
}
+FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
+ SourceLocation NameLoc,
+ unsigned NumParams,
+ Decl * const *Params)
+ : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary,
+ true, true, true, true),
+ ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
+ if (Params)
+ std::uninitialized_copy(Params, Params + NumParams,
+ reinterpret_cast<Decl**>(this+1));
+}
+
+FunctionParmPackExpr *
+FunctionParmPackExpr::Create(ASTContext &Context, QualType T,
+ ParmVarDecl *ParamPack, SourceLocation NameLoc,
+ llvm::ArrayRef<Decl*> Params) {
+ return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
+ sizeof(ParmVarDecl*) * Params.size()))
+ FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data());
+}
+
+FunctionParmPackExpr *
+FunctionParmPackExpr::CreateEmpty(ASTContext &Context, unsigned NumParams) {
+ return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
+ sizeof(ParmVarDecl*) * NumParams))
+ FunctionParmPackExpr(QualType(), 0, SourceLocation(), 0, 0);
+}
+
TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc,
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index f16d70b..24ec6bb 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -134,6 +134,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// ObjC instance variables are lvalues
// FIXME: ObjC++0x might have different rules
case Expr::ObjCIvarRefExprClass:
+ case Expr::FunctionParmPackExprClass:
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 06c41a2..6e0b5fc 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -953,7 +953,7 @@ static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) {
if (VD)
Info.Note(VD->getLocation(), diag::note_declared_at);
else
- Info.Note(Base.dyn_cast<const Expr*>()->getExprLoc(),
+ Info.Note(Base.get<const Expr*>()->getExprLoc(),
diag::note_constexpr_temporary_here);
}
@@ -987,6 +987,14 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
LVal.getLValueCallIndex() == 0) &&
"have call index for global lvalue");
+ // Check if this is a thread-local variable.
+ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
+ if (const VarDecl *Var = dyn_cast<const VarDecl>(VD)) {
+ if (Var->isThreadSpecified())
+ return false;
+ }
+ }
+
// Allow address constant expressions to be past-the-end pointers. This is
// an extension: the standard requires them to point to an object.
if (!IsReferenceType)
@@ -2586,7 +2594,7 @@ public:
const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
if (!FD) return Error(E);
assert(!FD->getType()->isReferenceType() && "prvalue reference?");
- assert(BaseTy->getAs<RecordType>()->getDecl()->getCanonicalDecl() ==
+ assert(BaseTy->castAs<RecordType>()->getDecl()->getCanonicalDecl() ==
FD->getParent()->getCanonicalDecl() && "record / field mismatch");
SubobjectDesignator Designator(BaseTy);
@@ -2665,7 +2673,7 @@ public:
if (E->isArrow()) {
if (!EvaluatePointer(E->getBase(), Result, this->Info))
return false;
- BaseTy = E->getBase()->getType()->getAs<PointerType>()->getPointeeType();
+ BaseTy = E->getBase()->getType()->castAs<PointerType>()->getPointeeType();
} else if (E->getBase()->isRValue()) {
assert(E->getBase()->getType()->isRecordType());
if (!EvaluateTemporary(E->getBase(), Result, this->Info))
@@ -2878,19 +2886,13 @@ LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
}
bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
- if (E->isTypeOperand())
+ if (!E->isPotentiallyEvaluated())
return Success(E);
- CXXRecordDecl *RD = E->getExprOperand()->getType()->getAsCXXRecordDecl();
- // FIXME: The standard says "a typeid expression whose operand is of a
- // polymorphic class type" is not a constant expression, but it probably
- // means "a typeid expression whose operand is potentially evaluated".
- if (RD && RD->isPolymorphic()) {
- Info.Diag(E, diag::note_constexpr_typeid_polymorphic)
- << E->getExprOperand()->getType()
- << E->getExprOperand()->getSourceRange();
- return false;
- }
- return Success(E);
+
+ Info.Diag(E, diag::note_constexpr_typeid_polymorphic)
+ << E->getExprOperand()->getType()
+ << E->getExprOperand()->getSourceRange();
+ return false;
}
bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
@@ -3036,7 +3038,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (E->getOpcode() == BO_Sub)
AdditionalOffset = -AdditionalOffset;
- QualType Pointee = PExp->getType()->getAs<PointerType>()->getPointeeType();
+ QualType Pointee = PExp->getType()->castAs<PointerType>()->getPointeeType();
return HandleLValueArrayAdjustment(Info, E, Result, Pointee,
AdditionalOffset);
}
@@ -4288,6 +4290,16 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Error(E);
}
+ case Builtin::BI__builtin_bswap16:
+ case Builtin::BI__builtin_bswap32:
+ case Builtin::BI__builtin_bswap64: {
+ APSInt Val;
+ if (!EvaluateInteger(E->getArg(0), Val, Info))
+ return false;
+
+ return Success(Val.byteSwap(), E);
+ }
+
case Builtin::BI__builtin_classify_type:
return Success(EvaluateBuiltinClassifyType(E), E);
@@ -4902,7 +4914,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero())
return false;
const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr*>();
- const Expr *RHSExpr = LHSValue.Base.dyn_cast<const Expr*>();
+ const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr*>();
if (!LHSExpr || !RHSExpr)
return false;
const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr);
@@ -5176,7 +5188,7 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
QualType Ty = E->getTypeOfArgument();
if (Ty->isVectorType()) {
- unsigned n = Ty->getAs<VectorType>()->getNumElements();
+ unsigned n = Ty->castAs<VectorType>()->getNumElements();
// The vec_step built-in functions that take a 3-component
// vector return 4. (OpenCL 1.1 spec 6.11.12)
@@ -5349,6 +5361,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_IntegralRealToComplex:
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
+ case CK_BuiltinFnToFnPtr:
llvm_unreachable("invalid cast kind for integral value");
case CK_BitCast:
@@ -5753,7 +5766,7 @@ static bool EvaluateComplex(const Expr *E, ComplexValue &Result,
}
bool ComplexExprEvaluator::ZeroInitialization(const Expr *E) {
- QualType ElemTy = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType ElemTy = E->getType()->castAs<ComplexType>()->getElementType();
if (ElemTy->isRealFloatingType()) {
Result.makeComplexFloat();
APFloat Zero = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(ElemTy));
@@ -5835,6 +5848,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
+ case CK_BuiltinFnToFnPtr:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
@@ -5911,9 +5925,9 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (!Visit(E->getSubExpr()))
return false;
- QualType To = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType To = E->getType()->castAs<ComplexType>()->getElementType();
QualType From
- = E->getSubExpr()->getType()->getAs<ComplexType>()->getElementType();
+ = E->getSubExpr()->getType()->castAs<ComplexType>()->getElementType();
Result.makeComplexFloat();
return HandleIntToFloatCast(Info, E, From, Result.IntReal,
To, Result.FloatReal) &&
@@ -6177,11 +6191,9 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
return false;
Result = Info.CurrentCall->Temporaries[E];
} else if (E->getType()->isVoidType()) {
- if (Info.getLangOpts().CPlusPlus0x)
+ if (!Info.getLangOpts().CPlusPlus0x)
Info.CCEDiag(E, diag::note_constexpr_nonliteral)
<< E->getType();
- else
- Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
if (!EvaluateVoid(E, Info))
return false;
} else if (Info.getLangOpts().CPlusPlus0x) {
@@ -6470,6 +6482,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::OpaqueValueExprClass:
case Expr::PackExpansionExprClass:
case Expr::SubstNonTypeTemplateParmPackExprClass:
+ case Expr::FunctionParmPackExprClass:
case Expr::AsTypeExprClass:
case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::MaterializeTemporaryExprClass:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 7c7a5e5..851944a 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -343,17 +343,10 @@ private:
void mangleCXXDtorType(CXXDtorType T);
void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);
- void mangleTemplateArgs(TemplateName Template,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs);
- void mangleTemplateArgs(const TemplateParameterList &PL,
- const TemplateArgument *TemplateArgs,
+ void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
- void mangleTemplateArgs(const TemplateParameterList &PL,
- const TemplateArgumentList &AL);
- void mangleTemplateArg(const NamedDecl *P, TemplateArgument A);
- void mangleUnresolvedTemplateArgs(const TemplateArgument *args,
- unsigned numArgs);
+ void mangleTemplateArgs(const TemplateArgumentList &AL);
+ void mangleTemplateArg(TemplateArgument A);
void mangleTemplateParameter(unsigned Index);
@@ -570,8 +563,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
const TemplateArgumentList *TemplateArgs = 0;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleUnscopedTemplateName(TD);
- TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
- mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
+ mangleTemplateArgs(*TemplateArgs);
return;
}
@@ -593,8 +585,7 @@ void CXXNameMangler::mangleName(const TemplateDecl *TD,
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
mangleUnscopedTemplateName(TD);
- TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
- mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs);
+ mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
} else {
mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
}
@@ -693,9 +684,10 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) {
void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
if (Value.isSigned() && Value.isNegative()) {
Out << 'n';
- Value.abs().print(Out, true);
- } else
- Value.print(Out, Value.isSigned());
+ Value.abs().print(Out, /*signed*/ false);
+ } else {
+ Value.print(Out, /*signed*/ false);
+ }
}
void CXXNameMangler::mangleNumber(int64_t Number) {
@@ -737,8 +729,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
// 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(TST->getTemplateName(), TST->getArgs(),
- TST->getNumArgs());
+ mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
} else if (const DependentTemplateSpecializationType *DTST
@@ -751,7 +742,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
// 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(Template, DTST->getArgs(), DTST->getNumArgs());
+ mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
} else {
// We use the QualType mangle type variant here because it handles
// substitutions.
@@ -942,7 +933,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
}
}
- mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
+ mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
break;
}
@@ -959,7 +950,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
const DependentTemplateSpecializationType *tst
= cast<DependentTemplateSpecializationType>(type);
mangleSourceName(tst->getIdentifier());
- mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
+ mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
break;
}
}
@@ -1228,8 +1219,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
const TemplateArgumentList *TemplateArgs = 0;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD);
- TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
- mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
+ mangleTemplateArgs(*TemplateArgs);
}
else {
manglePrefix(DC, NoFunction);
@@ -1246,8 +1236,7 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
Out << 'N';
mangleTemplatePrefix(TD);
- TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
- mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs);
+ mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
Out << 'E';
}
@@ -1341,11 +1330,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
}
Out << "Ul";
- DeclarationName Name
- = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
- const FunctionProtoType *Proto
- = cast<CXXMethodDecl>(*Lambda->lookup(Name).first)->getType()->
- getAs<FunctionProtoType>();
+ const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()->
+ getAs<FunctionProtoType>();
mangleBareFunctionType(Proto, /*MangleReturnType=*/false);
Out << "E";
@@ -1423,8 +1409,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
const TemplateArgumentList *TemplateArgs = 0;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD);
- TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
- mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
+ mangleTemplateArgs(*TemplateArgs);
}
else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND)))
return;
@@ -2110,6 +2095,7 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
// ::= Dv [<dimension expression>] _ <element type>
// <extended element type> ::= <element type>
// ::= p # AltiVec vector pixel
+// ::= b # Altivec vector bool
void CXXNameMangler::mangleType(const VectorType *T) {
if ((T->getVectorKind() == VectorType::NeonVector ||
T->getVectorKind() == VectorType::NeonPolyVector)) {
@@ -2174,7 +2160,7 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
// 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(T->getTemplateName(), T->getArgs(), T->getNumArgs());
+ mangleTemplateArgs(T->getArgs(), T->getNumArgs());
addSubstitution(QualType(T, 0));
}
}
@@ -2200,7 +2186,7 @@ void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
// 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(Prefix, T->getArgs(), T->getNumArgs());
+ mangleTemplateArgs(T->getArgs(), T->getNumArgs());
Out << 'E';
}
@@ -2414,7 +2400,6 @@ recurse:
case Expr::ExpressionTraitExprClass:
case Expr::VAArgExprClass:
case Expr::CXXUuidofExprClass:
- case Expr::CXXNoexceptExprClass:
case Expr::CUDAKernelCallExprClass:
case Expr::AsTypeExprClass:
case Expr::PseudoObjectExprClass:
@@ -2606,6 +2591,11 @@ recurse:
Out <<"_E";
break;
+ case Expr::CXXNoexceptExprClass:
+ Out << "nx";
+ mangleExpression(cast<CXXNoexceptExpr>(E)->getOperand());
+ break;
+
case Expr::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
@@ -2808,7 +2798,15 @@ recurse:
// };
Out << "_SUBSTPACK_";
break;
-
+
+ case Expr::FunctionParmPackExprClass: {
+ // FIXME: not clear how to mangle this!
+ const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);
+ Out << "v110_SUBSTPACK";
+ mangleFunctionParam(FPPE->getParameterPack());
+ break;
+ }
+
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity);
@@ -3043,50 +3041,28 @@ void CXXNameMangler::mangleTemplateArgs(
// <template-args> ::= I <template-arg>+ E
Out << 'I';
for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)
- mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[i].getArgument());
- Out << 'E';
-}
-
-void CXXNameMangler::mangleTemplateArgs(TemplateName Template,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
- if (TemplateDecl *TD = Template.getAsTemplateDecl())
- return mangleTemplateArgs(*TD->getTemplateParameters(), TemplateArgs,
- NumTemplateArgs);
-
- mangleUnresolvedTemplateArgs(TemplateArgs, NumTemplateArgs);
-}
-
-void CXXNameMangler::mangleUnresolvedTemplateArgs(const TemplateArgument *args,
- unsigned numArgs) {
- // <template-args> ::= I <template-arg>+ E
- Out << 'I';
- for (unsigned i = 0; i != numArgs; ++i)
- mangleTemplateArg(0, args[i]);
+ mangleTemplateArg(TemplateArgs.getTemplateArgs()[i].getArgument());
Out << 'E';
}
-void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
- const TemplateArgumentList &AL) {
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) {
// <template-args> ::= I <template-arg>+ E
Out << 'I';
for (unsigned i = 0, e = AL.size(); i != e; ++i)
- mangleTemplateArg(PL.getParam(i), AL[i]);
+ mangleTemplateArg(AL[i]);
Out << 'E';
}
-void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
- const TemplateArgument *TemplateArgs,
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
// <template-args> ::= I <template-arg>+ E
Out << 'I';
for (unsigned i = 0; i != NumTemplateArgs; ++i)
- mangleTemplateArg(PL.getParam(i), TemplateArgs[i]);
+ mangleTemplateArg(TemplateArgs[i]);
Out << 'E';
}
-void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
- TemplateArgument A) {
+void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
// <template-arg> ::= <type> # type or template
// ::= X <expression> E # expression
// ::= <expr-primary> # simple expressions
@@ -3135,25 +3111,12 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral());
break;
case TemplateArgument::Declaration: {
- assert(P && "Missing template parameter for declaration argument");
// <expr-primary> ::= L <mangled-name> E # external name
- // <expr-primary> ::= L <type> 0 E
// Clang produces AST's where pointer-to-member-function expressions
// and pointer-to-function expressions are represented as a declaration not
// an expression. We compensate for it here to produce the correct mangling.
- const NonTypeTemplateParmDecl *Parameter = cast<NonTypeTemplateParmDecl>(P);
-
- // Handle NULL pointer arguments.
- if (!A.getAsDecl()) {
- Out << "L";
- mangleType(Parameter->getType());
- Out << "0E";
- break;
- }
-
-
- NamedDecl *D = cast<NamedDecl>(A.getAsDecl());
- bool compensateMangling = !Parameter->getType()->isReferenceType();
+ ValueDecl *D = A.getAsDecl();
+ bool compensateMangling = !A.isDeclForReferenceParam();
if (compensateMangling) {
Out << 'X';
mangleOperatorName(OO_Amp, 1);
@@ -3176,14 +3139,20 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
break;
}
-
+ case TemplateArgument::NullPtr: {
+ // <expr-primary> ::= L <type> 0 E
+ Out << 'L';
+ mangleType(A.getNullPtrType());
+ Out << "0E";
+ break;
+ }
case TemplateArgument::Pack: {
// Note: proposal by Mike Herrick on 12/20/10
Out << 'J';
for (TemplateArgument::pack_iterator PA = A.pack_begin(),
PAEnd = A.pack_end();
PA != PAEnd; ++PA)
- mangleTemplateArg(P, *PA);
+ mangleTemplateArg(*PA);
Out << 'E';
}
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index e2cee7f..5d5b83d 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/ABI.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include <map>
@@ -56,7 +57,7 @@ public:
void mangleVariableEncoding(const VarDecl *VD);
void mangleNumber(int64_t Number);
void mangleNumber(const llvm::APSInt &Value);
- void mangleType(QualType T, SourceRange Range);
+ void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true);
private:
void disableBackReferences() { UseNameBackReferences = false; }
@@ -68,6 +69,7 @@ private:
void manglePostfix(const DeclContext *DC, bool NoFunction=false);
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
void mangleQualifiers(Qualifiers Quals, bool IsMember);
+ void manglePointerQualifiers(Qualifiers Quals);
void mangleUnscopedTemplateName(const TemplateDecl *ND);
void mangleTemplateInstantiationName(const TemplateDecl *TD,
@@ -75,7 +77,7 @@ private:
void mangleObjCMethodName(const ObjCMethodDecl *MD);
void mangleLocalName(const FunctionDecl *FD);
- void mangleTypeRepeated(QualType T, SourceRange Range);
+ void mangleArgumentType(QualType T, SourceRange Range);
// Declare manglers for every type class.
#define ABSTRACT_TYPE(CLASS, PARENT)
@@ -95,6 +97,7 @@ private:
void mangleFunctionClass(const FunctionDecl *FD);
void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Number);
+ void mangleExpression(const Expr *E);
void mangleThrowSpecification(const FunctionProtoType *T);
void mangleTemplateArgs(
@@ -266,18 +269,18 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
Out << '4';
// Now mangle the type.
// <variable-type> ::= <type> <cvr-qualifiers>
- // ::= <type> A # pointers, references, arrays
+ // ::= <type> <pointee-cvr-qualifiers> # pointers, references
// Pointers and references are odd. The type of 'int * const foo;' gets
// mangled as 'QAHA' instead of 'PAHB', for example.
TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc();
QualType Ty = TL.getType();
if (Ty->isPointerType() || Ty->isReferenceType()) {
mangleType(Ty, TL.getSourceRange());
- Out << 'A';
+ mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
} else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {
// Global arrays are funny, too.
mangleType(AT, true);
- Out << 'A';
+ mangleQualifiers(Ty.getQualifiers(), false);
} else {
mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange());
mangleQualifiers(Ty.getLocalQualifiers(), false);
@@ -304,39 +307,23 @@ void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
}
void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
- // <number> ::= [?] <decimal digit> # 1 <= Number <= 10
- // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc...
- // ::= [?] @ # 0 (alternate mangling, not emitted by VC)
- if (Number < 0) {
- Out << '?';
- Number = -Number;
- }
- // There's a special shorter mangling for 0, but Microsoft
- // chose not to use it. Instead, 0 gets mangled as "A@". Oh well...
- if (Number >= 1 && Number <= 10)
- Out << Number-1;
- else {
- // We have to build up the encoding in reverse order, so it will come
- // out right when we write it out.
- char Encoding[16];
- char *EndPtr = Encoding+sizeof(Encoding);
- char *CurPtr = EndPtr;
- do {
- *--CurPtr = 'A' + (Number % 16);
- Number /= 16;
- } while (Number);
- Out.write(CurPtr, EndPtr-CurPtr);
- Out << '@';
- }
+ llvm::APSInt APSNumber(/*BitWidth=*/64, /*isUnsigned=*/false);
+ APSNumber = Number;
+ mangleNumber(APSNumber);
}
void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
+ // <number> ::= [?] <decimal digit> # 1 <= Number <= 10
+ // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc...
+ // ::= [?] @ # 0 (alternate mangling, not emitted by VC)
if (Value.isSigned() && Value.isNegative()) {
Out << '?';
mangleNumber(llvm::APSInt(Value.abs()));
return;
}
llvm::APSInt Temp(Value);
+ // There's a special shorter mangling for 0, but Microsoft
+ // chose not to use it. Instead, 0 gets mangled as "A@". Oh well...
if (Value.uge(1) && Value.ule(10)) {
--Temp;
Temp.print(Out, false);
@@ -348,10 +335,10 @@ void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
char *CurPtr = EndPtr;
llvm::APSInt NibbleMask(Value.getBitWidth(), Value.isUnsigned());
NibbleMask = 0xf;
- for (int i = 0, e = Value.getActiveBits() / 4; i != e; ++i) {
+ do {
*--CurPtr = 'A' + Temp.And(NibbleMask).getLimitedValue(0xf);
Temp = Temp.lshr(4);
- }
+ } while (Temp != 0);
Out.write(CurPtr, EndPtr-CurPtr);
Out << '@';
}
@@ -386,7 +373,7 @@ isTemplate(const NamedDecl *ND,
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
TypeSourceInfo *TSI = Spec->getTypeAsWritten();
if (TSI) {
- TemplateSpecializationTypeLoc &TSTL =
+ TemplateSpecializationTypeLoc TSTL =
cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc());
TemplateArgumentListInfo LI(TSTL.getLAngleLoc(), TSTL.getRAngleLoc());
for (unsigned i = 0, e = TSTL.getNumArgs(); i != e; ++i)
@@ -784,6 +771,23 @@ MicrosoftCXXNameMangler::mangleIntegerLiteral(QualType T,
}
void
+MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
+ // See if this is a constant expression.
+ llvm::APSInt Value;
+ if (E->isIntegerConstantExpr(Value, Context.getASTContext())) {
+ mangleIntegerLiteral(E->getType(), Value);
+ return;
+ }
+
+ // As bad as this diagnostic is, it's better than crashing.
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot yet mangle expression type %0");
+ Diags.Report(E->getExprLoc(), DiagID)
+ << E->getStmtClassName() << E->getSourceRange();
+}
+
+void
MicrosoftCXXNameMangler::mangleTemplateArgs(
const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
// <template-args> ::= {<type> | <integer-literal>}+ @
@@ -800,21 +804,19 @@ MicrosoftCXXNameMangler::mangleTemplateArgs(
case TemplateArgument::Integral:
mangleIntegerLiteral(TA.getIntegralType(), TA.getAsIntegral());
break;
- case TemplateArgument::Expression: {
- // See if this is a constant expression.
- Expr *TAE = TA.getAsExpr();
- llvm::APSInt Value;
- if (TAE->isIntegerConstantExpr(Value, Context.getASTContext())) {
- mangleIntegerLiteral(TAE->getType(), Value);
- break;
- }
- /* fallthrough */
- } default: {
+ case TemplateArgument::Expression:
+ mangleExpression(TA.getAsExpr());
+ break;
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
+ case TemplateArgument::Pack: {
// Issue a diagnostic.
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this %select{ERROR|ERROR|pointer/reference|ERROR|"
- "template|template pack expansion|expression|parameter pack}0 "
+ "cannot mangle this %select{ERROR|ERROR|pointer/reference|nullptr|"
+ "integral|template|template pack expansion|ERROR|parameter pack}0 "
"template argument yet");
Diags.Report(TAL.getLocation(), DiagID)
<< TA.getKind()
@@ -879,43 +881,60 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
// ::= 3 # ?
// ::= 4 # ?
// ::= 5 # not really based
+ bool HasConst = Quals.hasConst(),
+ HasVolatile = Quals.hasVolatile();
if (!IsMember) {
- if (!Quals.hasVolatile()) {
- if (!Quals.hasConst())
- Out << 'A';
- else
- Out << 'B';
+ if (HasConst && HasVolatile) {
+ Out << 'D';
+ } else if (HasVolatile) {
+ Out << 'C';
+ } else if (HasConst) {
+ Out << 'B';
} else {
- if (!Quals.hasConst())
- Out << 'C';
- else
- Out << 'D';
+ Out << 'A';
}
} else {
- if (!Quals.hasVolatile()) {
- if (!Quals.hasConst())
- Out << 'Q';
- else
- Out << 'R';
+ if (HasConst && HasVolatile) {
+ Out << 'T';
+ } else if (HasVolatile) {
+ Out << 'S';
+ } else if (HasConst) {
+ Out << 'R';
} else {
- if (!Quals.hasConst())
- Out << 'S';
- else
- Out << 'T';
+ Out << 'Q';
}
}
// FIXME: For now, just drop all extension qualifiers on the floor.
}
-void MicrosoftCXXNameMangler::mangleTypeRepeated(QualType T, SourceRange Range) {
+void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) {
+ // <pointer-cvr-qualifiers> ::= P # no qualifiers
+ // ::= Q # const
+ // ::= R # volatile
+ // ::= S # const volatile
+ bool HasConst = Quals.hasConst(),
+ HasVolatile = Quals.hasVolatile();
+ if (HasConst && HasVolatile) {
+ Out << 'S';
+ } else if (HasVolatile) {
+ Out << 'R';
+ } else if (HasConst) {
+ Out << 'Q';
+ } else {
+ Out << 'P';
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
+ SourceRange Range) {
void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();
ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
if (Found == TypeBackReferences.end()) {
size_t OutSizeBefore = Out.GetNumBytesInBuffer();
- mangleType(T,Range);
+ mangleType(T, Range, false);
// See if it's worth creating a back reference.
// Only types longer than 1 character are considered
@@ -930,38 +949,30 @@ void MicrosoftCXXNameMangler::mangleTypeRepeated(QualType T, SourceRange Range)
}
}
-void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range) {
+void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
+ bool MangleQualifiers) {
// Only operate on the canonical type!
T = getASTContext().getCanonicalType(T);
-
+
Qualifiers Quals = T.getLocalQualifiers();
- if (Quals) {
- // We have to mangle these now, while we still have enough information.
- // <pointer-cvr-qualifiers> ::= P # pointer
- // ::= Q # const pointer
- // ::= R # volatile pointer
- // ::= S # const volatile pointer
- if (T->isAnyPointerType() || T->isMemberPointerType() ||
- T->isBlockPointerType()) {
- if (!Quals.hasVolatile())
- Out << 'Q';
- else {
- if (!Quals.hasConst())
- Out << 'R';
- else
- Out << 'S';
- }
- } else
- // Just emit qualifiers like normal.
- // NB: When we mangle a pointer/reference type, and the pointee
- // type has no qualifiers, the lack of qualifier gets mangled
- // in there.
- mangleQualifiers(Quals, false);
- } else if (T->isAnyPointerType() || T->isMemberPointerType() ||
- T->isBlockPointerType()) {
- Out << 'P';
+ // We have to mangle these now, while we still have enough information.
+ if (T->isAnyPointerType() || T->isMemberPointerType() ||
+ T->isBlockPointerType()) {
+ manglePointerQualifiers(Quals);
+ } else if (Quals && MangleQualifiers) {
+ mangleQualifiers(Quals, false);
}
- switch (T->getTypeClass()) {
+
+ SplitQualType split = T.split();
+ const Type *ty = split.Ty;
+
+ // If we're mangling a qualified array type, push the qualifiers to
+ // the element type.
+ if (split.Quals && isa<ArrayType>(T)) {
+ ty = Context.getASTContext().getAsArrayType(T);
+ }
+
+ switch (ty->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT) \
case Type::CLASS: \
@@ -969,7 +980,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range) {
return;
#define TYPE(CLASS, PARENT) \
case Type::CLASS: \
- mangleType(static_cast<const CLASS##Type*>(T.getTypePtr()), Range); \
+ mangleType(cast<CLASS##Type>(ty), Range); \
break;
#include "clang/AST/TypeNodes.def"
#undef ABSTRACT_TYPE
@@ -1059,6 +1070,8 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
SourceRange) {
// Structors only appear in decls, so at this point we know it's not a
// structor type.
+ // FIXME: This may not be lambda-friendly.
+ Out << "$$A6";
mangleType(T, NULL, false, false);
}
void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
@@ -1117,14 +1130,14 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {
TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();
QualType Type = TSI ? TSI->getType() : (*Parm)->getType();
- mangleTypeRepeated(Type, (*Parm)->getSourceRange());
+ mangleArgumentType(Type, (*Parm)->getSourceRange());
}
} else {
// Happens for function pointer type arguments for example.
for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
ArgEnd = Proto->arg_type_end();
Arg != ArgEnd; ++Arg)
- mangleTypeRepeated(*Arg, SourceRange());
+ mangleArgumentType(*Arg, SourceRange());
}
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
@@ -1214,7 +1227,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
if (CC == CC_Default) {
if (IsInstMethod) {
const FunctionProtoType *FPT =
- T->getCanonicalTypeUnqualified().getAs<FunctionProtoType>();
+ T->getCanonicalTypeUnqualified().castAs<FunctionProtoType>();
bool isVariadic = FPT->isVariadic();
CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic);
} else {
@@ -1260,10 +1273,10 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
// <class-type> ::= V <name>
// <enum-type> ::= W <size> <name>
void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {
- mangleType(static_cast<const TagType*>(T));
+ mangleType(cast<TagType>(T));
}
void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
- mangleType(static_cast<const TagType*>(T));
+ mangleType(cast<TagType>(T));
}
void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
switch (T->getDecl()->getTagKind()) {
@@ -1271,6 +1284,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
Out << 'T';
break;
case TTK_Struct:
+ case TTK_Interface:
Out << 'U';
break;
case TTK_Class:
@@ -1286,37 +1300,39 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
}
// <type> ::= <array-type>
-// <array-type> ::= P <cvr-qualifiers> [Y <dimension-count> <dimension>+]
-// <element-type> # as global
+// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
+// [Y <dimension-count> <dimension>+]
+// <element-type> # as global
// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
-// <element-type> # as param
+// <element-type> # as param
// It's supposed to be the other way around, but for some strange reason, it
// isn't. Today this behavior is retained for the sole purpose of backwards
// compatibility.
void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) {
// This isn't a recursive mangling, so now we have to do it all in this
// one call.
- if (IsGlobal)
- Out << 'P';
- else
+ if (IsGlobal) {
+ manglePointerQualifiers(T->getElementType().getQualifiers());
+ } else {
Out << 'Q';
+ }
mangleExtraDimensions(T->getElementType());
}
void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
SourceRange) {
- mangleType(static_cast<const ArrayType *>(T), false);
+ mangleType(cast<ArrayType>(T), false);
}
void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T,
SourceRange) {
- mangleType(static_cast<const ArrayType *>(T), false);
+ mangleType(cast<ArrayType>(T), false);
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,
SourceRange) {
- mangleType(static_cast<const ArrayType *>(T), false);
+ mangleType(cast<ArrayType>(T), false);
}
void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
SourceRange) {
- mangleType(static_cast<const ArrayType *>(T), false);
+ mangleType(cast<ArrayType>(T), false);
}
void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
SmallVector<llvm::APInt, 3> Dimensions;
@@ -1409,10 +1425,8 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
Out << '6';
mangleType(FT, NULL, false, false);
} else {
- if (!PointeeTy.hasQualifiers())
- // Lack of qualifiers is mangled as 'A'.
- Out << 'A';
- mangleType(PointeeTy, Range);
+ mangleQualifiers(PointeeTy.getQualifiers(), false);
+ mangleType(PointeeTy, Range, false);
}
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
@@ -1497,7 +1511,9 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
SourceRange Range) {
Out << "_E";
- mangleType(T->getPointeeType(), Range);
+
+ QualType pointee = T->getPointeeType();
+ mangleType(pointee->castAs<FunctionProtoType>(), NULL, false, false);
}
void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T,
diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp
index 39077d1..0837509 100644
--- a/lib/AST/NSAPI.cpp
+++ b/lib/AST/NSAPI.cpp
@@ -344,6 +344,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::ARCUnbridgedCast:
case BuiltinType::Half:
case BuiltinType::PseudoObject:
+ case BuiltinType::BuiltinFn:
break;
}
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index fa87afd..1135928 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -20,22 +20,63 @@ using namespace clang;
typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
-static void BuildParentMap(MapTy& M, Stmt* S) {
- for (Stmt::child_range I = S->children(); I; ++I)
- if (*I) {
- // Prefer the first time we see this statement in the traversal.
- // This is important for PseudoObjectExprs.
- Stmt *&Parent = M[*I];
- if (!Parent) {
- Parent = S;
- BuildParentMap(M, *I);
+enum OpaqueValueMode {
+ OV_Transparent,
+ OV_Opaque
+};
+
+static void BuildParentMap(MapTy& M, Stmt* S,
+ OpaqueValueMode OVMode = OV_Transparent) {
+
+ switch (S->getStmtClass()) {
+ case Stmt::PseudoObjectExprClass: {
+ assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
+ PseudoObjectExpr *POE = cast<PseudoObjectExpr>(S);
+
+ M[POE->getSyntacticForm()] = S;
+ BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
+
+ for (PseudoObjectExpr::semantics_iterator I = POE->semantics_begin(),
+ E = POE->semantics_end();
+ I != E; ++I) {
+ M[*I] = S;
+ BuildParentMap(M, *I, OV_Opaque);
+ }
+ break;
+ }
+ case Stmt::BinaryConditionalOperatorClass: {
+ assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
+ BinaryConditionalOperator *BCO = cast<BinaryConditionalOperator>(S);
+
+ M[BCO->getCommon()] = S;
+ BuildParentMap(M, BCO->getCommon(), OV_Transparent);
+
+ M[BCO->getCond()] = S;
+ BuildParentMap(M, BCO->getCond(), OV_Opaque);
+
+ M[BCO->getTrueExpr()] = S;
+ BuildParentMap(M, BCO->getTrueExpr(), OV_Opaque);
+
+ M[BCO->getFalseExpr()] = S;
+ BuildParentMap(M, BCO->getFalseExpr(), OV_Transparent);
+
+ break;
+ }
+ case Stmt::OpaqueValueExprClass:
+ if (OVMode == OV_Transparent) {
+ OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(S);
+ M[OVE->getSourceExpr()] = S;
+ BuildParentMap(M, OVE->getSourceExpr(), OV_Transparent);
+ }
+ break;
+ default:
+ for (Stmt::child_range I = S->children(); I; ++I) {
+ if (*I) {
+ M[*I] = S;
+ BuildParentMap(M, *I, OVMode);
}
}
-
- // Also include the source expr tree of an OpaqueValueExpr in the map.
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {
- M[OVE->getSourceExpr()] = S;
- BuildParentMap(M, OVE->getSourceExpr());
+ break;
}
}
diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp
index a5a3287..80b6272 100644
--- a/lib/AST/RawCommentList.cpp
+++ b/lib/AST/RawCommentList.cpp
@@ -143,11 +143,10 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const {
// a separate allocator for all temporary stuff.
llvm::BumpPtrAllocator Allocator;
- comments::CommandTraits Traits;
- comments::Lexer L(Allocator, Traits,
- Range.getBegin(), comments::CommentOptions(),
+ comments::Lexer L(Allocator, Context.getCommentCommandTraits(),
+ Range.getBegin(),
RawText.begin(), RawText.end());
- comments::BriefParser P(L, Traits);
+ comments::BriefParser P(L, Context.getCommentCommandTraits());
const std::string Result = P.Parse();
const unsigned BriefTextLength = Result.size();
@@ -160,19 +159,22 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const {
}
comments::FullComment *RawComment::parse(const ASTContext &Context,
+ const Preprocessor *PP,
const Decl *D) const {
// Make sure that RawText is valid.
getRawText(Context.getSourceManager());
- comments::CommandTraits Traits;
- comments::Lexer L(Context.getAllocator(), Traits,
- getSourceRange().getBegin(), comments::CommentOptions(),
+ comments::Lexer L(Context.getAllocator(), Context.getCommentCommandTraits(),
+ getSourceRange().getBegin(),
RawText.begin(), RawText.end());
comments::Sema S(Context.getAllocator(), Context.getSourceManager(),
- Context.getDiagnostics(), Traits);
+ Context.getDiagnostics(),
+ Context.getCommentCommandTraits(),
+ PP);
S.setDecl(D);
comments::Parser P(L, S, Context.getAllocator(), Context.getSourceManager(),
- Context.getDiagnostics(), Traits);
+ Context.getDiagnostics(),
+ Context.getCommentCommandTraits());
return P.parseFullComment();
}
@@ -182,26 +184,22 @@ bool containsOnlyWhitespace(StringRef Str) {
return Str.find_first_not_of(" \t\f\v\r\n") == StringRef::npos;
}
-bool onlyWhitespaceBetweenComments(SourceManager &SM,
- const RawComment &C1, const RawComment &C2) {
- std::pair<FileID, unsigned> C1EndLocInfo = SM.getDecomposedLoc(
- C1.getSourceRange().getEnd());
- std::pair<FileID, unsigned> C2BeginLocInfo = SM.getDecomposedLoc(
- C2.getSourceRange().getBegin());
+bool onlyWhitespaceBetween(SourceManager &SM,
+ SourceLocation Loc1, SourceLocation Loc2) {
+ std::pair<FileID, unsigned> Loc1Info = SM.getDecomposedLoc(Loc1);
+ std::pair<FileID, unsigned> Loc2Info = SM.getDecomposedLoc(Loc2);
- // Question does not make sense if comments are located in different files.
- if (C1EndLocInfo.first != C2BeginLocInfo.first)
+ // Question does not make sense if locations are in different files.
+ if (Loc1Info.first != Loc2Info.first)
return false;
bool Invalid = false;
- const char *Buffer = SM.getBufferData(C1EndLocInfo.first, &Invalid).data();
+ const char *Buffer = SM.getBufferData(Loc1Info.first, &Invalid).data();
if (Invalid)
return false;
- StringRef TextBetweenComments(Buffer + C1EndLocInfo.second,
- C2BeginLocInfo.second - C1EndLocInfo.second);
-
- return containsOnlyWhitespace(TextBetweenComments);
+ StringRef Text(Buffer + Loc1Info.second, Loc2Info.second - Loc1Info.second);
+ return containsOnlyWhitespace(Text);
}
} // unnamed namespace
@@ -221,11 +219,13 @@ void RawCommentList::addComment(const RawComment &RC,
}
if (OnlyWhitespaceSeen) {
- if (!onlyWhitespaceBetweenComments(SourceMgr, LastComment, RC))
+ if (!onlyWhitespaceBetween(SourceMgr,
+ PrevCommentEndLoc,
+ RC.getSourceRange().getBegin()))
OnlyWhitespaceSeen = false;
}
- LastComment = RC;
+ PrevCommentEndLoc = RC.getSourceRange().getEnd();
// Ordinary comments are not interesting for us.
if (RC.isOrdinary())
@@ -244,15 +244,20 @@ void RawCommentList::addComment(const RawComment &RC,
// Merge comments only if there is only whitespace between them.
// Can't merge trailing and non-trailing comments.
- // Merge trailing comments if they are on same or consecutive lines.
+ // Merge comments if they are on same or consecutive lines.
+ bool Merged = false;
if (OnlyWhitespaceSeen &&
- (C1.isTrailingComment() == C2.isTrailingComment()) &&
- (!C1.isTrailingComment() ||
- C1.getEndLine(SourceMgr) + 1 >= C2.getBeginLine(SourceMgr))) {
- SourceRange MergedRange(C1.getSourceRange().getBegin(),
- C2.getSourceRange().getEnd());
- *Comments.back() = RawComment(SourceMgr, MergedRange, true);
- } else
+ (C1.isTrailingComment() == C2.isTrailingComment())) {
+ unsigned C1EndLine = C1.getEndLine(SourceMgr);
+ unsigned C2BeginLine = C2.getBeginLine(SourceMgr);
+ if (C1EndLine + 1 == C2BeginLine || C1EndLine == C2BeginLine) {
+ SourceRange MergedRange(C1.getSourceRange().getBegin(),
+ C2.getSourceRange().getEnd());
+ *Comments.back() = RawComment(SourceMgr, MergedRange, true);
+ Merged = true;
+ }
+ }
+ if (!Merged)
Comments.push_back(new (Allocator) RawComment(RC));
OnlyWhitespaceSeen = true;
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index d5df63f..4dfffc4 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -789,8 +789,8 @@ protected:
void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
- RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
- void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
+ RecordLayoutBuilder(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
+ void operator=(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
public:
static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
};
@@ -1557,6 +1557,13 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
(void)Allowed;
assert(Allowed && "Base subobject externally placed at overlapping offset");
+
+ if (InferAlignment && Offset < getDataSize().RoundUpToAlignment(BaseAlign)){
+ // The externally-supplied base offset is before the base offset we
+ // computed. Assume that the structure is packed.
+ Alignment = CharUnits::One();
+ InferAlignment = false;
+ }
}
if (!Base->Class->isEmpty()) {
@@ -1574,12 +1581,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
}
void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
IsUnion = RD->isUnion();
+ IsMsStruct = RD->isMsStruct(Context);
+ }
- Packed = D->hasAttr<PackedAttr>();
-
- IsMsStruct = D->hasAttr<MsStructAttr>();
+ Packed = D->hasAttr<PackedAttr>();
// Honor the default struct packing maximum alignment flag.
if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) {
@@ -1616,7 +1623,6 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
if (ExternalLayout) {
if (ExternalAlign > 0) {
Alignment = Context.toCharUnitsFromBits(ExternalAlign);
- UnpackedAlignment = Alignment;
} else {
// The external source didn't have alignment information; infer it.
InferAlignment = true;
@@ -2085,7 +2091,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
ZeroLengthBitfield = 0;
}
- if (Context.getLangOpts().MSBitfields || IsMsStruct) {
+ if (IsMsStruct) {
// If MS bitfield layout is required, figure out what type is being
// laid out and align the field to the width of that type.
@@ -2166,11 +2172,6 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
}
void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
- if (ExternalLayout) {
- setSize(ExternalSize);
- return;
- }
-
// In C++, records cannot be of size 0.
if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
@@ -2184,20 +2185,37 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
setSize(CharUnits::One());
}
+ // Finally, round the size of the record up to the alignment of the
+ // record itself.
+ uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte;
+ uint64_t UnpackedSizeInBits =
+ llvm::RoundUpToAlignment(getSizeInBits(),
+ Context.toBits(UnpackedAlignment));
+ CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits);
+ uint64_t RoundedSize
+ = llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment));
+
+ if (ExternalLayout) {
+ // 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) {
+ Alignment = CharUnits::One();
+ InferAlignment = false;
+ }
+ setSize(ExternalSize);
+ return;
+ }
+
+
// MSVC doesn't round up to the alignment of the record with virtual bases.
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
if (isMicrosoftCXXABI() && RD->getNumVBases())
return;
}
- // Finally, round the size of the record up to the alignment of the
- // record itself.
- uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte;
- uint64_t UnpackedSizeInBits =
- llvm::RoundUpToAlignment(getSizeInBits(),
- Context.toBits(UnpackedAlignment));
- CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits);
- setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment)));
+ // Set the size to the final size.
+ setSize(RoundedSize);
unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
@@ -2255,7 +2273,7 @@ RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
// The externally-supplied field offset is before the field offset we
// computed. Assume that the structure is packed.
- Alignment = CharUnits::fromQuantity(1);
+ Alignment = CharUnits::One();
InferAlignment = false;
}
@@ -2263,6 +2281,20 @@ RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
return ExternalFieldOffset;
}
+/// \brief Get diagnostic %select index for tag kind for
+/// field padding diagnostic message.
+/// WARNING: Indexes apply to particular diagnostics only!
+///
+/// \returns diagnostic %select index.
+static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag) {
+ switch (Tag) {
+ case TTK_Struct: return 0;
+ case TTK_Interface: return 1;
+ case TTK_Class: return 2;
+ default: llvm_unreachable("Invalid tag kind for field padding diagnostic!");
+ }
+}
+
void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
uint64_t UnpaddedOffset,
uint64_t UnpackedOffset,
@@ -2291,14 +2323,14 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
}
if (D->getIdentifier())
Diag(D->getLocation(), diag::warn_padded_struct_field)
- << (D->getParent()->isStruct() ? 0 : 1) // struct|class
+ << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
<< Context.getTypeDeclType(D->getParent())
<< PadSize
<< (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
<< D->getIdentifier();
else
Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
- << (D->getParent()->isStruct() ? 0 : 1) // struct|class
+ << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
<< Context.getTypeDeclType(D->getParent())
<< PadSize
<< (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
@@ -2508,8 +2540,8 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
assert(D && D->isThisDeclarationADefinition() && "Invalid interface decl!");
// Look up this layout, if already laid out, return what we have.
- ObjCContainerDecl *Key =
- Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D;
+ const ObjCContainerDecl *Key =
+ Impl ? (const ObjCContainerDecl*) Impl : (const ObjCContainerDecl*) D;
if (const ASTRecordLayout *Entry = ObjCLayouts[Key])
return *Entry;
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 77452c9..eafcf92 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -320,15 +321,52 @@ bool Stmt::hasImplicitControlFlow() const {
}
}
-Expr *AsmStmt::getOutputExpr(unsigned i) {
- return cast<Expr>(Exprs[i]);
+std::string AsmStmt::generateAsmString(ASTContext &C) const {
+ if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ return gccAsmStmt->generateAsmString(C);
+ if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ return msAsmStmt->generateAsmString(C);
+ llvm_unreachable("unknown asm statement kind!");
}
-/// getOutputConstraint - Return the constraint string for the specified
-/// output operand. All output constraints are known to be non-empty (either
-/// '=' or '+').
StringRef AsmStmt::getOutputConstraint(unsigned i) const {
- return getOutputConstraintLiteral(i)->getString();
+ if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ return gccAsmStmt->getOutputConstraint(i);
+ if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ return msAsmStmt->getOutputConstraint(i);
+ llvm_unreachable("unknown asm statement kind!");
+}
+
+const Expr *AsmStmt::getOutputExpr(unsigned i) const {
+ if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ return gccAsmStmt->getOutputExpr(i);
+ if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ return msAsmStmt->getOutputExpr(i);
+ llvm_unreachable("unknown asm statement kind!");
+}
+
+StringRef AsmStmt::getInputConstraint(unsigned i) const {
+ if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ return gccAsmStmt->getInputConstraint(i);
+ if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ return msAsmStmt->getInputConstraint(i);
+ llvm_unreachable("unknown asm statement kind!");
+}
+
+const Expr *AsmStmt::getInputExpr(unsigned i) const {
+ if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ return gccAsmStmt->getInputExpr(i);
+ if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ return msAsmStmt->getInputExpr(i);
+ llvm_unreachable("unknown asm statement kind!");
+}
+
+StringRef AsmStmt::getClobber(unsigned i) const {
+ if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
+ return gccAsmStmt->getClobber(i);
+ if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
+ return msAsmStmt->getClobber(i);
+ llvm_unreachable("unknown asm statement kind!");
}
/// getNumPlusOperands - Return the number of output operands that have a "+"
@@ -341,22 +379,35 @@ unsigned AsmStmt::getNumPlusOperands() const {
return Res;
}
-Expr *AsmStmt::getInputExpr(unsigned i) {
+StringRef GCCAsmStmt::getClobber(unsigned i) const {
+ return getClobberStringLiteral(i)->getString();
+}
+
+Expr *GCCAsmStmt::getOutputExpr(unsigned i) {
+ return cast<Expr>(Exprs[i]);
+}
+
+/// getOutputConstraint - Return the constraint string for the specified
+/// output operand. All output constraints are known to be non-empty (either
+/// '=' or '+').
+StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
+ return getOutputConstraintLiteral(i)->getString();
+}
+
+Expr *GCCAsmStmt::getInputExpr(unsigned i) {
return cast<Expr>(Exprs[i + NumOutputs]);
}
-void AsmStmt::setInputExpr(unsigned i, Expr *E) {
+void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
Exprs[i + NumOutputs] = E;
}
-
/// getInputConstraint - Return the specified input constraint. Unlike output
/// constraints, these can be empty.
-StringRef AsmStmt::getInputConstraint(unsigned i) const {
+StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
return getInputConstraintLiteral(i)->getString();
}
-
-void AsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C,
+void GCCAsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C,
IdentifierInfo **Names,
StringLiteral **Constraints,
Stmt **Exprs,
@@ -390,7 +441,7 @@ void AsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C,
/// getNamedOperand - Given a symbolic operand reference like %[foo],
/// translate this into a numeric value needed to reference the same operand.
/// This returns -1 if the operand name is invalid.
-int AsmStmt::getNamedOperand(StringRef SymbolicName) const {
+int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const {
unsigned NumPlusOperands = 0;
// Check if this is an output operand.
@@ -410,7 +461,7 @@ int AsmStmt::getNamedOperand(StringRef SymbolicName) const {
/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
/// it into pieces. If the asm string is erroneous, emit errors and return
/// true, otherwise return false.
-unsigned AsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
+unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
ASTContext &C, unsigned &DiagOffs) const {
StringRef Str = getAsmString()->getString();
const char *StrStart = Str.begin();
@@ -548,6 +599,44 @@ unsigned AsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
}
}
+/// Assemble final IR asm string (GCC-style).
+std::string GCCAsmStmt::generateAsmString(ASTContext &C) const {
+ // Analyze the asm string to decompose it into its pieces. We know that Sema
+ // has already done this, so it is guaranteed to be successful.
+ SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces;
+ unsigned DiagOffs;
+ AnalyzeAsmString(Pieces, C, DiagOffs);
+
+ std::string AsmString;
+ for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
+ if (Pieces[i].isString())
+ AsmString += Pieces[i].getString();
+ else if (Pieces[i].getModifier() == '\0')
+ AsmString += '$' + llvm::utostr(Pieces[i].getOperandNo());
+ else
+ AsmString += "${" + llvm::utostr(Pieces[i].getOperandNo()) + ':' +
+ Pieces[i].getModifier() + '}';
+ }
+ return AsmString;
+}
+
+/// Assemble final IR asm string (MS-style).
+std::string MSAsmStmt::generateAsmString(ASTContext &C) const {
+ // FIXME: This needs to be translated into the IR string representation.
+ return AsmStr;
+}
+
+Expr *MSAsmStmt::getOutputExpr(unsigned i) {
+ return cast<Expr>(Exprs[i]);
+}
+
+Expr *MSAsmStmt::getInputExpr(unsigned i) {
+ return cast<Expr>(Exprs[i + NumOutputs]);
+}
+void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
+ Exprs[i + NumOutputs] = E;
+}
+
QualType CXXCatchStmt::getCaughtType() const {
if (ExceptionDecl)
return ExceptionDecl->getType();
@@ -558,15 +647,14 @@ QualType CXXCatchStmt::getCaughtType() const {
// Constructors
//===----------------------------------------------------------------------===//
-AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
- bool isvolatile, bool msasm,
- unsigned numoutputs, unsigned numinputs,
- IdentifierInfo **names, StringLiteral **constraints,
- Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
- StringLiteral **clobbers, SourceLocation rparenloc)
- : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
- , IsSimple(issimple), IsVolatile(isvolatile), MSAsm(msasm)
- , NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) {
+GCCAsmStmt::GCCAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
+ bool isvolatile, unsigned numoutputs, unsigned numinputs,
+ IdentifierInfo **names, StringLiteral **constraints,
+ Expr **exprs, StringLiteral *asmstr,
+ unsigned numclobbers, StringLiteral **clobbers,
+ SourceLocation rparenloc)
+ : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
+ numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) {
unsigned NumExprs = NumOutputs + NumInputs;
@@ -585,26 +673,37 @@ AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
MSAsmStmt::MSAsmStmt(ASTContext &C, SourceLocation asmloc,
SourceLocation lbraceloc, bool issimple, bool isvolatile,
- ArrayRef<Token> asmtoks, ArrayRef<IdentifierInfo*> inputs,
- ArrayRef<IdentifierInfo*> outputs, StringRef asmstr,
- ArrayRef<StringRef> clobbers, SourceLocation endloc)
- : Stmt(MSAsmStmtClass), AsmLoc(asmloc), LBraceLoc(lbraceloc), EndLoc(endloc),
- AsmStr(asmstr.str()), IsSimple(issimple), IsVolatile(isvolatile),
- NumAsmToks(asmtoks.size()), NumInputs(inputs.size()),
- NumOutputs(outputs.size()), NumClobbers(clobbers.size()) {
+ ArrayRef<Token> asmtoks, unsigned numoutputs,
+ unsigned numinputs, ArrayRef<IdentifierInfo*> names,
+ ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs,
+ StringRef asmstr, ArrayRef<StringRef> clobbers,
+ SourceLocation endloc)
+ : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
+ numinputs, clobbers.size()), LBraceLoc(lbraceloc),
+ EndLoc(endloc), AsmStr(asmstr.str()), NumAsmToks(asmtoks.size()) {
unsigned NumExprs = NumOutputs + NumInputs;
Names = new (C) IdentifierInfo*[NumExprs];
- for (unsigned i = 0, e = NumOutputs; i != e; ++i)
- Names[i] = outputs[i];
- for (unsigned i = NumOutputs, e = NumExprs; i != e; ++i)
- Names[i] = inputs[i];
+ for (unsigned i = 0, e = NumExprs; i != e; ++i)
+ Names[i] = names[i];
+
+ Exprs = new (C) Stmt*[NumExprs];
+ for (unsigned i = 0, e = NumExprs; i != e; ++i)
+ Exprs[i] = exprs[i];
AsmToks = new (C) Token[NumAsmToks];
for (unsigned i = 0, e = NumAsmToks; i != e; ++i)
AsmToks[i] = asmtoks[i];
+ Constraints = new (C) StringRef[NumExprs];
+ for (unsigned i = 0, e = NumExprs; i != e; ++i) {
+ size_t size = constraints[i].size();
+ char *dest = new (C) char[size];
+ std::strncpy(dest, constraints[i].data(), size);
+ Constraints[i] = StringRef(dest, size);
+ }
+
Clobbers = new (C) StringRef[NumClobbers];
for (unsigned i = 0, e = NumClobbers; i != e; ++i) {
// FIXME: Avoid the allocation/copy if at all possible.
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index 962e352..fbc990f 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the Stmt::dump/Stmt::print methods, which dump out the
+// This file implements the Stmt::dump method, which dumps out the
// AST in a form that exposes type details and other fields.
//
//===----------------------------------------------------------------------===//
@@ -30,6 +30,7 @@ namespace {
SourceManager *SM;
raw_ostream &OS;
unsigned IndentLevel;
+ bool IsFirstLine;
/// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump
/// the first few levels of an AST. This keeps track of how many ast levels
@@ -41,46 +42,64 @@ namespace {
const char *LastLocFilename;
unsigned LastLocLine;
+ class IndentScope {
+ StmtDumper &Dumper;
+ public:
+ IndentScope(StmtDumper &Dumper) : Dumper(Dumper) {
+ Dumper.indent();
+ }
+ ~IndentScope() {
+ Dumper.unindent();
+ }
+ };
+
public:
StmtDumper(SourceManager *sm, raw_ostream &os, unsigned maxDepth)
- : SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) {
+ : SM(sm), OS(os), IndentLevel(0), IsFirstLine(true), MaxDepth(maxDepth) {
LastLocFilename = "";
LastLocLine = ~0U;
}
+ ~StmtDumper() {
+ OS << "\n";
+ }
+
void DumpSubTree(Stmt *S) {
// Prune the recursion if not using dump all.
if (MaxDepth == 0) return;
- ++IndentLevel;
- if (S) {
- if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
- VisitDeclStmt(DS);
- else {
- Visit(S);
-
- // Print out children.
- Stmt::child_range CI = S->children();
- if (CI) {
- while (CI) {
- OS << '\n';
- DumpSubTree(*CI++);
- }
- }
- }
- OS << ')';
- } else {
- Indent();
+ IndentScope Indent(*this);
+
+ if (!S) {
OS << "<<<NULL>>>";
+ return;
+ }
+
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
+ VisitDeclStmt(DS);
+ return;
}
- --IndentLevel;
+
+ Visit(S);
+ for (Stmt::child_range CI = S->children(); CI; CI++)
+ DumpSubTree(*CI);
}
void DumpDeclarator(Decl *D);
- void Indent() const {
- for (int i = 0, e = IndentLevel; i < e; ++i)
- OS << " ";
+ void indent() {
+ if (IsFirstLine)
+ IsFirstLine = false;
+ else
+ OS << "\n";
+ OS.indent(IndentLevel * 2);
+ OS << "(";
+ IndentLevel++;
+ }
+
+ void unindent() {
+ OS << ")";
+ IndentLevel--;
}
void DumpType(QualType T) {
@@ -96,9 +115,8 @@ namespace {
}
void DumpDeclRef(Decl *node);
void DumpStmt(const Stmt *Node) {
- Indent();
- OS << "(" << Node->getStmtClassName()
- << " " << (void*)Node;
+ OS << Node->getStmtClassName()
+ << " " << (const void*)Node;
DumpSourceRange(Node);
}
void DumpValueKind(ExprValueKind K) {
@@ -262,7 +280,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
// If this is a vardecl with an initializer, emit it.
if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
if (V->getInit()) {
- OS << " =\n";
+ OS << " =";
DumpSubTree(V->getInit());
}
}
@@ -294,9 +312,9 @@ void StmtDumper::DumpDeclarator(Decl *D) {
} else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
OS << "label " << *LD;
} else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) {
- OS << "\"static_assert(\n";
+ OS << "\"static_assert(";
DumpSubTree(SAD->getAssertExpr());
- OS << ",\n";
+ OS << ",";
DumpSubTree(SAD->getMessage());
OS << ");\"";
} else {
@@ -306,17 +324,12 @@ void StmtDumper::DumpDeclarator(Decl *D) {
void StmtDumper::VisitDeclStmt(DeclStmt *Node) {
DumpStmt(Node);
- OS << "\n";
for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
DI != DE; ++DI) {
+ IndentScope Indent(*this);
Decl* D = *DI;
- ++IndentLevel;
- Indent();
OS << (void*) D << " ";
DumpDeclarator(D);
- if (DI+1 != DE)
- OS << "\n";
- --IndentLevel;
}
}
@@ -503,35 +516,29 @@ void StmtDumper::VisitBlockExpr(BlockExpr *Node) {
BlockDecl *block = Node->getBlockDecl();
OS << " decl=" << block;
- IndentLevel++;
if (block->capturesCXXThis()) {
- OS << '\n'; Indent(); OS << "(capture this)";
+ IndentScope Indent(*this);
+ OS << "capture this";
}
for (BlockDecl::capture_iterator
i = block->capture_begin(), e = block->capture_end(); i != e; ++i) {
- OS << '\n';
- Indent();
- OS << "(capture ";
+ IndentScope Indent(*this);
+ OS << "capture ";
if (i->isByRef()) OS << "byref ";
if (i->isNested()) OS << "nested ";
if (i->getVariable())
DumpDeclRef(i->getVariable());
if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr());
- OS << ")";
}
- IndentLevel--;
- OS << '\n';
DumpSubTree(block->getBody());
}
void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
DumpExpr(Node);
- if (Expr *Source = Node->getSourceExpr()) {
- OS << '\n';
+ if (Expr *Source = Node->getSourceExpr())
DumpSubTree(Source);
- }
}
// GNU extensions.
@@ -589,15 +596,11 @@ void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) {
DumpExpr(Node);
- ++IndentLevel;
for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) {
- OS << "\n";
- Indent();
- OS << "(cleanup ";
+ IndentScope Indent(*this);
+ OS << "cleanup ";
DumpDeclRef(Node->getObject(i));
- OS << ")";
}
- --IndentLevel;
}
void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) {
@@ -734,7 +737,6 @@ void Stmt::dump(SourceManager &SM) const {
void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
StmtDumper P(&SM, OS, 4);
P.DumpSubTree(const_cast<Stmt*>(this));
- OS << "\n";
}
/// dump - This does a local dump of the specified AST fragment. It dumps the
@@ -743,19 +745,16 @@ void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
void Stmt::dump() const {
StmtDumper P(0, llvm::errs(), 4);
P.DumpSubTree(const_cast<Stmt*>(this));
- llvm::errs() << "\n";
}
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void Stmt::dumpAll(SourceManager &SM) const {
StmtDumper P(&SM, llvm::errs(), ~0U);
P.DumpSubTree(const_cast<Stmt*>(this));
- llvm::errs() << "\n";
}
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void Stmt::dumpAll() const {
StmtDumper P(0, llvm::errs(), ~0U);
P.DumpSubTree(const_cast<Stmt*>(this));
- llvm::errs() << "\n";
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index c0960ce..57eb1a9 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -61,7 +61,7 @@ namespace {
void PrintRawCompoundStmt(CompoundStmt *S);
void PrintRawDecl(Decl *D);
- void PrintRawDeclStmt(DeclStmt *S);
+ void PrintRawDeclStmt(const DeclStmt *S);
void PrintRawIfStmt(IfStmt *If);
void PrintRawCXXCatchStmt(CXXCatchStmt *Catch);
void PrintCallArgs(CallExpr *E);
@@ -121,8 +121,8 @@ void StmtPrinter::PrintRawDecl(Decl *D) {
D->print(OS, Policy, IndentLevel);
}
-void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) {
- DeclStmt::decl_iterator Begin = S->decl_begin(), End = S->decl_end();
+void StmtPrinter::PrintRawDeclStmt(const DeclStmt *S) {
+ DeclStmt::const_decl_iterator Begin = S->decl_begin(), End = S->decl_end();
SmallVector<Decl*, 2> Decls;
for ( ; Begin != End; ++Begin)
Decls.push_back(*Begin);
@@ -187,7 +187,10 @@ void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
OS << "if (";
- PrintExpr(If->getCond());
+ if (const DeclStmt *DS = If->getConditionVariableDeclStmt())
+ PrintRawDeclStmt(DS);
+ else
+ PrintExpr(If->getCond());
OS << ')';
if (CompoundStmt *CS = dyn_cast<CompoundStmt>(If->getThen())) {
@@ -224,7 +227,10 @@ void StmtPrinter::VisitIfStmt(IfStmt *If) {
void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) {
Indent() << "switch (";
- PrintExpr(Node->getCond());
+ if (const DeclStmt *DS = Node->getConditionVariableDeclStmt())
+ PrintRawDeclStmt(DS);
+ else
+ PrintExpr(Node->getCond());
OS << ")";
// Pretty print compoundstmt bodies (very common).
@@ -240,7 +246,10 @@ void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) {
void StmtPrinter::VisitWhileStmt(WhileStmt *Node) {
Indent() << "while (";
- PrintExpr(Node->getCond());
+ if (const DeclStmt *DS = Node->getConditionVariableDeclStmt())
+ PrintRawDeclStmt(DS);
+ else
+ PrintExpr(Node->getCond());
OS << ")\n";
PrintStmt(Node->getBody());
}
@@ -366,7 +375,7 @@ void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
}
-void StmtPrinter::VisitAsmStmt(AsmStmt *Node) {
+void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
Indent() << "asm ";
if (Node->isVolatile())
@@ -422,7 +431,7 @@ void StmtPrinter::VisitAsmStmt(AsmStmt *Node) {
if (i != 0)
OS << ", ";
- VisitStringLiteral(Node->getClobber(i));
+ VisitStringLiteral(Node->getClobberStringLiteral(i));
}
OS << ");\n";
@@ -734,10 +743,30 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
case BuiltinType::UInt128: OS << "Ui128"; break;
}
}
-void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
+
+static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
+ bool PrintSuffix) {
SmallString<16> Str;
Node->getValue().toString(Str);
OS << Str;
+ if (Str.find_first_not_of("-0123456789") == StringRef::npos)
+ OS << '.'; // Trailing dot in order to separate from ints.
+
+ if (!PrintSuffix)
+ return;
+
+ // Emit suffixes. Float literals are always a builtin float type.
+ switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
+ default: llvm_unreachable("Unexpected type for float literal!");
+ case BuiltinType::Half: break; // FIXME: suffix?
+ case BuiltinType::Double: break; // no suffix.
+ case BuiltinType::Float: OS << 'F'; break;
+ case BuiltinType::LongDouble: OS << 'L'; break;
+ }
+}
+
+void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
+ PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true);
}
void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) {
@@ -907,7 +936,7 @@ void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
OS << Node->getAccessor().getName();
}
void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
- OS << "(" << Node->getType().getAsString(Policy) << ")";
+ OS << "(" << Node->getTypeAsWritten().getAsString(Policy) << ")";
PrintExpr(Node->getSubExpr());
}
void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) {
@@ -1110,6 +1139,8 @@ void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
PrintExpr(Node->getArg(0));
OS << ' ' << OpStrings[Kind];
}
+ } else if (Kind == OO_Arrow) {
+ PrintExpr(Node->getArg(0));
} else if (Kind == OO_Call) {
PrintExpr(Node->getArg(0));
OS << '(';
@@ -1217,7 +1248,12 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
OS << Int->getValue().toString(10, /*isSigned*/false);
break;
}
- case UserDefinedLiteral::LOK_Floating:
+ case UserDefinedLiteral::LOK_Floating: {
+ // Print floating literal without suffix.
+ FloatingLiteral *Float = cast<FloatingLiteral>(Node->getCookedLiteral());
+ PrintFloatingLiteral(OS, Float, /*PrintSuffix=*/false);
+ break;
+ }
case UserDefinedLiteral::LOK_String:
case UserDefinedLiteral::LOK_Character:
PrintExpr(Node->getCookedLiteral());
@@ -1379,10 +1415,12 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
OS << "::";
OS << "new ";
unsigned NumPlace = E->getNumPlacementArgs();
- if (NumPlace > 0) {
+ if (NumPlace > 0 && !isa<CXXDefaultArgExpr>(E->getPlacementArg(0))) {
OS << "(";
PrintExpr(E->getPlacementArg(0));
for (unsigned i = 1; i < NumPlace; ++i) {
+ if (isa<CXXDefaultArgExpr>(E->getPlacementArg(i)))
+ break;
OS << ", ";
PrintExpr(E->getPlacementArg(i));
}
@@ -1429,6 +1467,7 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
OS << '.';
if (E->getQualifier())
E->getQualifier()->print(OS, Policy);
+ OS << "~";
std::string TypeS;
if (IdentifierInfo *II = E->getDestroyedTypeIdentifier())
@@ -1531,6 +1570,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) {
case UTT_IsFunction: return "__is_function";
case UTT_IsFundamental: return "__is_fundamental";
case UTT_IsIntegral: return "__is_integral";
+ case UTT_IsInterfaceClass: return "__is_interface_class";
case UTT_IsLiteral: return "__is_literal";
case UTT_IsLvalueReference: return "__is_lvalue_reference";
case UTT_IsMemberFunctionPointer: return "__is_member_function_pointer";
@@ -1647,6 +1687,10 @@ void StmtPrinter::VisitSubstNonTypeTemplateParmExpr(
Visit(Node->getReplacement());
}
+void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
+ OS << *E->getParameterPack();
+}
+
void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
PrintExpr(Node->GetTemporaryExpr());
}
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 2168b64..bfd3132 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -158,7 +158,7 @@ void StmtProfiler::VisitReturnStmt(const ReturnStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitAsmStmt(const AsmStmt *S) {
+void StmtProfiler::VisitGCCAsmStmt(const GCCAsmStmt *S) {
VisitStmt(S);
ID.AddBoolean(S->isVolatile());
ID.AddBoolean(S->isSimple());
@@ -175,7 +175,7 @@ void StmtProfiler::VisitAsmStmt(const AsmStmt *S) {
}
ID.AddInteger(S->getNumClobbers());
for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
- VisitStringLiteral(S->getClobber(I));
+ VisitStringLiteral(S->getClobberStringLiteral(I));
}
void StmtProfiler::VisitMSAsmStmt(const MSAsmStmt *S) {
@@ -973,6 +973,14 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmExpr(
Visit(E->getReplacement());
}
+void StmtProfiler::VisitFunctionParmPackExpr(const FunctionParmPackExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getParameterPack());
+ ID.AddInteger(S->getNumExpansions());
+ for (FunctionParmPackExpr::iterator I = S->begin(), E = S->end(); I != E; ++I)
+ VisitDecl(*I);
+}
+
void StmtProfiler::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *S) {
VisitExpr(S);
@@ -1165,6 +1173,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
VisitDecl(Arg.getAsDecl());
break;
+ case TemplateArgument::NullPtr:
+ VisitType(Arg.getNullPtrType());
+ break;
+
case TemplateArgument::Integral:
Arg.getAsIntegral().Profile(ID);
VisitType(Arg.getIntegralType());
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 95ff4ed..e9ee385 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -77,7 +77,7 @@ TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
const TemplateArgument *Args,
unsigned NumArgs) {
if (NumArgs == 0)
- return TemplateArgument(0, 0);
+ return getEmptyPack();
TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
std::copy(Args, Args + NumArgs, Storage);
@@ -99,12 +99,11 @@ bool TemplateArgument::isDependent() const {
return true;
case Declaration:
- if (Decl *D = getAsDecl()) {
- if (DeclContext *DC = dyn_cast<DeclContext>(D))
- return DC->isDependentContext();
- return D->getDeclContext()->isDependentContext();
- }
-
+ if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
+ return DC->isDependentContext();
+ return getAsDecl()->getDeclContext()->isDependentContext();
+
+ case NullPtr:
return false;
case Integral:
@@ -141,11 +140,11 @@ bool TemplateArgument::isInstantiationDependent() const {
return true;
case Declaration:
- if (Decl *D = getAsDecl()) {
- if (DeclContext *DC = dyn_cast<DeclContext>(D))
- return DC->isDependentContext();
- return D->getDeclContext()->isDependentContext();
- }
+ if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
+ return DC->isDependentContext();
+ return getAsDecl()->getDeclContext()->isDependentContext();
+
+ case NullPtr:
return false;
case Integral:
@@ -174,6 +173,7 @@ bool TemplateArgument::isPackExpansion() const {
case Integral:
case Pack:
case Template:
+ case NullPtr:
return false;
case TemplateExpansion:
@@ -195,6 +195,7 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
case Declaration:
case Integral:
case TemplateExpansion:
+ case NullPtr:
break;
case Type:
@@ -286,12 +287,16 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
switch (getKind()) {
case Null:
case Type:
- case Declaration:
case Expression:
case Template:
case TemplateExpansion:
+ case NullPtr:
return TypeOrValue == Other.TypeOrValue;
+ case Declaration:
+ return getAsDecl() == Other.getAsDecl() &&
+ isDeclForReferenceParam() && Other.isDeclForReferenceParam();
+
case Integral:
return getIntegralType() == Other.getIntegralType() &&
getAsIntegral() == Other.getAsIntegral();
@@ -319,12 +324,13 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
case TemplateExpansion:
return TemplateArgument(getAsTemplateOrTemplatePattern());
-
+
case Declaration:
case Integral:
case Pack:
case Null:
case Template:
+ case NullPtr:
return TemplateArgument();
}
@@ -348,18 +354,20 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
}
case Declaration: {
- if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
- if (ND->getDeclName()) {
- Out << *ND;
- } else {
- Out << "<anonymous>";
- }
+ NamedDecl *ND = cast<NamedDecl>(getAsDecl());
+ if (ND->getDeclName()) {
+ // FIXME: distinguish between pointer and reference args?
+ Out << *ND;
} else {
- Out << "nullptr";
+ Out << "<anonymous>";
}
break;
}
-
+
+ case NullPtr:
+ Out << "nullptr";
+ break;
+
case Template:
getAsTemplate().print(Out, Policy);
break;
@@ -411,6 +419,9 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
case TemplateArgument::Declaration:
return getSourceDeclExpression()->getSourceRange();
+ case TemplateArgument::NullPtr:
+ return getSourceNullPtrExpression()->getSourceRange();
+
case TemplateArgument::Type:
if (TypeSourceInfo *TSI = getTypeSourceInfo())
return TSI->getTypeLoc().getSourceRange();
@@ -430,6 +441,8 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
case TemplateArgument::Integral:
+ return getSourceIntegralExpression()->getSourceRange();
+
case TemplateArgument::Pack:
case TemplateArgument::Null:
return SourceRange();
@@ -490,6 +503,7 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
getTemplateNameLoc());
case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
case TemplateArgument::Template:
case TemplateArgument::Integral:
case TemplateArgument::Pack:
@@ -512,8 +526,9 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
return DB << Arg.getAsType();
case TemplateArgument::Declaration:
- if (Decl *D = Arg.getAsDecl())
- return DB << D;
+ return DB << Arg.getAsDecl();
+
+ case TemplateArgument::NullPtr:
return DB << "nullptr";
case TemplateArgument::Integral:
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index abefae4..580ec50 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -288,18 +288,17 @@ QualType QualType::IgnoreParens(QualType T) {
return T;
}
-/// \brief This will check for a TypedefType by removing any existing sugar
-/// until it reaches a TypedefType or a non-sugared type.
-template <> const TypedefType *Type::getAs() const {
- const Type *Cur = this;
-
+/// \brief This will check for a T (which should be a Type which can act as
+/// sugar, such as a TypedefType) by removing any existing sugar until it
+/// reaches a T or a non-sugared type.
+template<typename T> static const T *getAsSugar(const Type *Cur) {
while (true) {
- if (const TypedefType *TDT = dyn_cast<TypedefType>(Cur))
- return TDT;
+ if (const T *Sugar = dyn_cast<T>(Cur))
+ return Sugar;
switch (Cur->getTypeClass()) {
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
- case Class: { \
+ case Type::Class: { \
const Class##Type *Ty = cast<Class##Type>(Cur); \
if (!Ty->isSugared()) return 0; \
Cur = Ty->desugar().getTypePtr(); \
@@ -310,6 +309,14 @@ template <> const TypedefType *Type::getAs() const {
}
}
+template <> const TypedefType *Type::getAs() const {
+ return getAsSugar<TypedefType>(this);
+}
+
+template <> const TemplateSpecializationType *Type::getAs() const {
+ return getAsSugar<TemplateSpecializationType>(this);
+}
+
/// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic
/// sugar off the given type. This should produce an object of the
/// same dynamic type as the canonical type.
@@ -357,9 +364,15 @@ bool Type::isStructureType() const {
return RT->getDecl()->isStruct();
return false;
}
+bool Type::isInterfaceType() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return RT->getDecl()->isInterface();
+ return false;
+}
bool Type::isStructureOrClassType() const {
if (const RecordType *RT = getAs<RecordType>())
- return RT->getDecl()->isStruct() || RT->getDecl()->isClass();
+ return RT->getDecl()->isStruct() || RT->getDecl()->isClass() ||
+ RT->getDecl()->isInterface();
return false;
}
bool Type::isVoidPointerType() const {
@@ -499,10 +512,18 @@ const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
return 0;
}
-const CXXRecordDecl *Type::getCXXRecordDeclForPointerType() const {
+const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const {
+ QualType PointeeType;
if (const PointerType *PT = getAs<PointerType>())
- if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>())
- return dyn_cast<CXXRecordDecl>(RT->getDecl());
+ PointeeType = PT->getPointeeType();
+ else if (const ReferenceType *RT = getAs<ReferenceType>())
+ PointeeType = RT->getPointeeType();
+ else
+ return 0;
+
+ if (const RecordType *RT = PointeeType->getAs<RecordType>())
+ return dyn_cast<CXXRecordDecl>(RT->getDecl());
+
return 0;
}
@@ -1205,8 +1226,6 @@ bool QualType::isCXX11PODType(ASTContext &Context) const {
return false;
case Qualifiers::OCL_None:
- if (ty->isObjCLifetimeType())
- return false;
break;
}
}
@@ -1317,6 +1336,7 @@ TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) {
case TST_typename: return ETK_Typename;
case TST_class: return ETK_Class;
case TST_struct: return ETK_Struct;
+ case TST_interface: return ETK_Interface;
case TST_union: return ETK_Union;
case TST_enum: return ETK_Enum;
}
@@ -1327,6 +1347,7 @@ TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
switch(TypeSpec) {
case TST_class: return TTK_Class;
case TST_struct: return TTK_Struct;
+ case TST_interface: return TTK_Interface;
case TST_union: return TTK_Union;
case TST_enum: return TTK_Enum;
}
@@ -1339,6 +1360,7 @@ TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) {
switch (Kind) {
case TTK_Class: return ETK_Class;
case TTK_Struct: return ETK_Struct;
+ case TTK_Interface: return ETK_Interface;
case TTK_Union: return ETK_Union;
case TTK_Enum: return ETK_Enum;
}
@@ -1350,6 +1372,7 @@ TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) {
switch (Keyword) {
case ETK_Class: return TTK_Class;
case ETK_Struct: return TTK_Struct;
+ case ETK_Interface: return TTK_Interface;
case ETK_Union: return TTK_Union;
case ETK_Enum: return TTK_Enum;
case ETK_None: // Fall through.
@@ -1367,6 +1390,7 @@ TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
return false;
case ETK_Class:
case ETK_Struct:
+ case ETK_Interface:
case ETK_Union:
case ETK_Enum:
return true;
@@ -1381,6 +1405,7 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
case ETK_Typename: return "typename";
case ETK_Class: return "class";
case ETK_Struct: return "struct";
+ case ETK_Interface: return "__interface";
case ETK_Union: return "union";
case ETK_Enum: return "enum";
}
@@ -1480,6 +1505,7 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
case Dependent: return "<dependent type>";
case UnknownAny: return "<unknown type>";
case ARCUnbridgedCast: return "<ARC unbridged cast type>";
+ case BuiltinFn: return "<builtin fn type>";
case ObjCId: return "id";
case ObjCClass: return "Class";
case ObjCSel: return "SEL";
@@ -1516,6 +1542,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86Pascal: return "pascal";
case CC_AAPCS: return "aapcs";
case CC_AAPCS_VFP: return "aapcs-vfp";
+ case CC_PnaclCall: return "pnaclcall";
}
llvm_unreachable("Invalid calling convention.");
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index c7bb7da..58c4cbd 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -98,23 +98,38 @@ void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
SourceLocation TypeLoc::getBeginLoc() const {
TypeLoc Cur = *this;
+ TypeLoc LeftMost = Cur;
while (true) {
switch (Cur.getTypeLocClass()) {
- // FIXME: Currently QualifiedTypeLoc does not have a source range
- // case Qualified:
case Elaborated:
- case DependentName:
- case DependentTemplateSpecialization:
+ LeftMost = Cur;
break;
+ case FunctionProto:
+ if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) {
+ LeftMost = Cur;
+ break;
+ }
+ /* Fall through */
+ case FunctionNoProto:
+ case ConstantArray:
+ case DependentSizedArray:
+ case IncompleteArray:
+ case VariableArray:
+ // FIXME: Currently QualifiedTypeLoc does not have a source range
+ case Qualified:
+ Cur = Cur.getNextTypeLoc();
+ continue;
default:
- TypeLoc Next = Cur.getNextTypeLoc();
- if (Next.isNull()) break;
- Cur = Next;
+ if (!Cur.getLocalSourceRange().getBegin().isInvalid())
+ LeftMost = Cur;
+ Cur = Cur.getNextTypeLoc();
+ if (Cur.isNull())
+ break;
continue;
- }
+ } // switch
break;
- }
- return Cur.getLocalSourceRange().getBegin();
+ } // while
+ return LeftMost.getLocalSourceRange().getBegin();
}
SourceLocation TypeLoc::getEndLoc() const {
@@ -131,10 +146,15 @@ SourceLocation TypeLoc::getEndLoc() const {
case DependentSizedArray:
case IncompleteArray:
case VariableArray:
- case FunctionProto:
case FunctionNoProto:
Last = Cur;
break;
+ case FunctionProto:
+ if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn())
+ Last = TypeLoc();
+ else
+ Last = Cur;
+ break;
case Pointer:
case BlockPointer:
case MemberPointer:
@@ -241,6 +261,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
+ case BuiltinType::BuiltinFn:
return TST_unspecified;
}
@@ -300,7 +321,9 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
case TemplateArgument::Null:
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
- case TemplateArgument::Pack:
+ case TemplateArgument::NullPtr:
+ llvm_unreachable("Impossible TemplateArgument");
+
case TemplateArgument::Expression:
ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
break;
@@ -310,7 +333,7 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
Loc));
break;
-
+
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
NestedNameSpecifierLocBuilder Builder;
@@ -327,7 +350,11 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
? SourceLocation()
: Loc);
break;
- }
+ }
+
+ case TemplateArgument::Pack:
+ ArgInfos[i] = TemplateArgumentLocInfo();
+ break;
}
}
}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index c42117c..90b2ca9 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -141,9 +141,6 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS,
OS << "NULL TYPE";
return;
}
-
- if (Policy.SuppressSpecifiers && T->isSpecifierType())
- return;
SaveAndRestore<bool> PHVal(HasEmptyPlaceHolder, PlaceHolder.empty());
@@ -556,7 +553,8 @@ void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
void
FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
- PrintingPolicy Policy) const {
+ const PrintingPolicy &Policy)
+ const {
if (hasDynamicExceptionSpec()) {
OS << " throw(";
@@ -646,6 +644,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_AAPCS_VFP:
OS << " __attribute__((pcs(\"aapcs-vfp\")))";
break;
+ case CC_PnaclCall:
+ OS << " __attribute__((pnaclcall))";
+ break;
}
if (Info.getNoReturn())
OS << " __attribute__((noreturn))";
@@ -798,6 +799,7 @@ void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
/// Appends the given scope to the end of a string.
void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
if (DC->isTranslationUnit()) return;
+ if (DC->isFunctionOrMethod()) return;
AppendScope(DC->getParent(), OS);
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
@@ -1165,6 +1167,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
OS << ')';
break;
}
+ case AttributedType::attr_pnaclcall: OS << "pnaclcall"; break;
}
OS << "))";
}
@@ -1343,7 +1346,8 @@ PrintTemplateArgumentList(raw_ostream &OS,
void
FunctionProtoType::printExceptionSpecification(std::string &S,
- PrintingPolicy Policy) const {
+ const PrintingPolicy &Policy)
+ const {
if (hasDynamicExceptionSpec()) {
S += " throw(";
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index 104530f..33dad40 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -1891,6 +1891,9 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) {
if (MD->isPure())
Out << " [pure]";
+ if (MD->isDeleted())
+ Out << " [deleted]";
+
ThunkInfo Thunk = VTableThunks.lookup(I);
if (!Thunk.isEmpty()) {
// If this function pointer has a return adjustment, dump it.
OpenPOWER on IntegriCloud