aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2010-09-17 15:54:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2010-09-17 15:54:40 +0000
commit3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f (patch)
tree0bbe07708f7571f8b5291f6d7b96c102b7c99dee /lib/AST
parenta0482fa4e7fa27b01184f938097f0666b78016dd (diff)
downloadsrc-3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f.tar.gz
src-3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f.zip
Vendor import of clang r114020 (from the release_28 branch):vendor/clang/clang-r114020
Notes
Notes: svn path=/vendor/clang/dist/; revision=212795 svn path=/vendor/clang/clang-r114020/; revision=212796; tag=vendor/clang/clang-r114020
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTConsumer.cpp3
-rw-r--r--lib/AST/ASTContext.cpp595
-rw-r--r--lib/AST/ASTDiagnostic.cpp11
-rw-r--r--lib/AST/ASTImporter.cpp104
-rw-r--r--lib/AST/AttrImpl.cpp196
-rw-r--r--lib/AST/CMakeLists.txt4
-rw-r--r--lib/AST/CXXABI.h39
-rw-r--r--lib/AST/Decl.cpp272
-rw-r--r--lib/AST/DeclBase.cpp251
-rw-r--r--lib/AST/DeclCXX.cpp109
-rw-r--r--lib/AST/DeclGroup.cpp6
-rw-r--r--lib/AST/DeclObjC.cpp183
-rw-r--r--lib/AST/DeclPrinter.cpp19
-rw-r--r--lib/AST/DeclTemplate.cpp174
-rw-r--r--lib/AST/DeclarationName.cpp116
-rw-r--r--lib/AST/Expr.cpp589
-rw-r--r--lib/AST/ExprCXX.cpp329
-rw-r--r--lib/AST/ExprClassification.cpp34
-rw-r--r--lib/AST/ExprConstant.cpp505
-rw-r--r--lib/AST/FullExpr.cpp13
-rw-r--r--lib/AST/ItaniumCXXABI.cpp52
-rw-r--r--lib/AST/Makefile1
-rw-r--r--lib/AST/MicrosoftCXXABI.cpp48
-rw-r--r--lib/AST/NestedNameSpecifier.cpp5
-rw-r--r--lib/AST/ParentMap.cpp2
-rw-r--r--lib/AST/RecordLayout.cpp4
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp113
-rw-r--r--lib/AST/Stmt.cpp94
-rw-r--r--lib/AST/StmtDumper.cpp38
-rw-r--r--lib/AST/StmtPrinter.cpp92
-rw-r--r--lib/AST/StmtProfile.cpp107
-rw-r--r--lib/AST/TemplateBase.cpp17
-rw-r--r--lib/AST/Type.cpp157
-rw-r--r--lib/AST/TypeLoc.cpp14
-rw-r--r--lib/AST/TypePrinter.cpp9
35 files changed, 2336 insertions, 1969 deletions
diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp
index f37cbdea5480..04a084a06a44 100644
--- a/lib/AST/ASTConsumer.cpp
+++ b/lib/AST/ASTConsumer.cpp
@@ -17,3 +17,6 @@ using namespace clang;
void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {}
+void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
+ HandleTopLevelDecl(D);
+}
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d41051f5dcad..4591a0f3c55c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -28,6 +28,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "CXXABI.h"
using namespace clang;
@@ -134,11 +135,25 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
return CanonTTP;
}
+CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
+ if (!LangOpts.CPlusPlus) return 0;
+
+ switch (T.getCXXABI()) {
+ case CXXABI_ARM:
+ return CreateARMCXXABI(*this);
+ case CXXABI_Itanium:
+ return CreateItaniumCXXABI(*this);
+ case CXXABI_Microsoft:
+ return CreateMicrosoftCXXABI(*this);
+ }
+ return 0;
+}
+
ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
- bool FreeMem, unsigned size_reserve) :
+ unsigned size_reserve) :
TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()),
GlobalNestedNameSpecifier(0), IsInt128Installed(false),
@@ -146,7 +161,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
NullTypeSourceInfo(QualType()),
- SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t),
+ SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)), Target(t),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins),
DeclarationNames(*this),
@@ -155,7 +170,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
- ObjCSelRedefinitionType = QualType();
+ ObjCSelRedefinitionType = QualType();
if (size_reserve > 0) Types.reserve(size_reserve);
TUDecl = TranslationUnitDecl::Create(*this);
InitBuiltinTypes();
@@ -166,11 +181,9 @@ ASTContext::~ASTContext() {
// FIXME: Is this the ideal solution?
ReleaseDeclContextMaps();
- if (!FreeMemory) {
- // Call all of the deallocation functions.
- for (unsigned I = 0, N = Deallocations.size(); I != N; ++I)
- Deallocations[I].first(Deallocations[I].second);
- }
+ // Call all of the deallocation functions.
+ for (unsigned I = 0, N = Deallocations.size(); I != N; ++I)
+ Deallocations[I].first(Deallocations[I].second);
// Release all of the memory associated with overridden C++ methods.
for (llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::iterator
@@ -178,51 +191,26 @@ ASTContext::~ASTContext() {
OM != OMEnd; ++OM)
OM->second.Destroy();
- if (FreeMemory) {
- // Deallocate all the types.
- while (!Types.empty()) {
- Types.back()->Destroy(*this);
- Types.pop_back();
- }
-
- for (llvm::FoldingSet<ExtQuals>::iterator
- I = ExtQualNodes.begin(), E = ExtQualNodes.end(); I != E; ) {
- // Increment in loop to prevent using deallocated memory.
- Deallocate(&*I++);
- }
-
- for (llvm::DenseMap<const ObjCContainerDecl*,
- const ASTRecordLayout*>::iterator
- I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; ) {
- // Increment in loop to prevent using deallocated memory.
- if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
- R->Destroy(*this);
- }
- }
-
// ASTRecordLayout objects in ASTRecordLayouts must always be destroyed
- // even when using the BumpPtrAllocator because they can contain
- // DenseMaps.
- for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
- I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
+ // because they can contain DenseMaps.
+ for (llvm::DenseMap<const ObjCContainerDecl*,
+ const ASTRecordLayout*>::iterator
+ I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; )
// Increment in loop to prevent using deallocated memory.
if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
R->Destroy(*this);
- }
- // Destroy nested-name-specifiers.
- for (llvm::FoldingSet<NestedNameSpecifier>::iterator
- NNS = NestedNameSpecifiers.begin(),
- NNSEnd = NestedNameSpecifiers.end();
- NNS != NNSEnd; ) {
+ for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
+ I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
// Increment in loop to prevent using deallocated memory.
- (*NNS++).Destroy(*this);
+ if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
+ R->Destroy(*this);
}
-
- if (GlobalNestedNameSpecifier)
- GlobalNestedNameSpecifier->Destroy(*this);
-
- TUDecl->Destroy(*this);
+
+ for (llvm::DenseMap<const Decl*, AttrVec*>::iterator A = DeclAttrs.begin(),
+ AEnd = DeclAttrs.end();
+ A != AEnd; ++A)
+ A->second->~AttrVec();
}
void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
@@ -275,16 +263,12 @@ void ASTContext::PrintStats() const {
fprintf(stderr, " %u/%u implicit destructors created\n",
NumImplicitDestructorsDeclared, NumImplicitDestructors);
- if (!FreeMemory)
- BumpAlloc.PrintStats();
-
if (ExternalSource.get()) {
fprintf(stderr, "\n");
ExternalSource->PrintStats();
}
- if (!FreeMemory)
- BumpAlloc.PrintStats();
+ BumpAlloc.PrintStats();
}
@@ -385,6 +369,26 @@ void ASTContext::InitBuiltinTypes() {
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
}
+AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
+ AttrVec *&Result = DeclAttrs[D];
+ if (!Result) {
+ void *Mem = Allocate(sizeof(AttrVec));
+ Result = new (Mem) AttrVec;
+ }
+
+ return *Result;
+}
+
+/// \brief Erase the attributes corresponding to the given declaration.
+void ASTContext::eraseDeclAttrs(const Decl *D) {
+ llvm::DenseMap<const Decl*, AttrVec*>::iterator Pos = DeclAttrs.find(D);
+ if (Pos != DeclAttrs.end()) {
+ Pos->second->~AttrVec();
+ DeclAttrs.erase(Pos);
+ }
+}
+
+
MemberSpecializationInfo *
ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
assert(Var->isStaticDataMember() && "Not a static data member");
@@ -499,20 +503,6 @@ void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
OverriddenMethods[Method].push_back(Overridden);
}
-namespace {
- class BeforeInTranslationUnit
- : std::binary_function<SourceRange, SourceRange, bool> {
- SourceManager *SourceMgr;
-
- public:
- explicit BeforeInTranslationUnit(SourceManager *SM) : SourceMgr(SM) { }
-
- bool operator()(SourceRange X, SourceRange Y) {
- return SourceMgr->isBeforeInTranslationUnit(X.getBegin(), Y.getBegin());
- }
- };
-}
-
//===----------------------------------------------------------------------===//
// Type Sizing and Analysis
//===----------------------------------------------------------------------===//
@@ -538,8 +528,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
unsigned Align = Target.getCharWidth();
- if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
- Align = std::max(Align, AA->getMaxAlignment());
+ Align = std::max(Align, D->getMaxAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType();
@@ -716,6 +705,12 @@ ASTContext::getTypeInfo(const Type *T) {
Width = Target.getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)
Align = Target.getPointerAlign(0); // == sizeof(void*)
break;
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ Width = Target.getPointerWidth(0);
+ Align = Target.getPointerAlign(0);
+ break;
}
break;
case Type::ObjCObjectPointer:
@@ -744,12 +739,10 @@ ASTContext::getTypeInfo(const Type *T) {
break;
}
case Type::MemberPointer: {
- QualType Pointee = cast<MemberPointerType>(T)->getPointeeType();
+ const MemberPointerType *MPT = cast<MemberPointerType>(T);
std::pair<uint64_t, unsigned> PtrDiffInfo =
getTypeInfo(getPointerDiffType());
- Width = PtrDiffInfo.first;
- if (Pointee->isFunctionType())
- Width *= 2;
+ Width = PtrDiffInfo.first * ABI->getMemberPointerSize(MPT);
Align = PtrDiffInfo.second;
break;
}
@@ -797,12 +790,10 @@ ASTContext::getTypeInfo(const Type *T) {
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
- if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
- Align = std::max(Aligned->getMaxAlignment(),
- getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
- Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
- } else
- return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
+ std::pair<uint64_t, unsigned> Info
+ = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
+ Align = std::max(Typedef->getMaxAlignment(), Info.second);
+ Width = Info.first;
break;
}
@@ -868,60 +859,37 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) {
return ABIAlign;
}
-static void CollectLocalObjCIvars(ASTContext *Ctx,
- const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<FieldDecl*> &Fields) {
- for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
- E = OI->ivar_end(); I != E; ++I) {
- ObjCIvarDecl *IVDecl = *I;
- if (!IVDecl->isInvalidDecl())
- Fields.push_back(cast<FieldDecl>(IVDecl));
- }
-}
-
-void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<FieldDecl*> &Fields) {
- if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
- CollectObjCIvars(SuperClass, Fields);
- CollectLocalObjCIvars(this, OI, Fields);
-}
-
/// ShallowCollectObjCIvars -
/// Collect all ivars, including those synthesized, in the current class.
///
void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
- for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
- E = OI->ivar_end(); I != E; ++I) {
- Ivars.push_back(*I);
- }
-
- CollectNonClassIvars(OI, Ivars);
-}
-
-/// CollectNonClassIvars -
-/// This routine collects all other ivars which are not declared in the class.
-/// This includes synthesized ivars (via @synthesize) and those in
-// class's @implementation.
+ // FIXME. This need be removed but there are two many places which
+ // assume const-ness of ObjCInterfaceDecl
+ ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
+ for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
+ Iv= Iv->getNextIvar())
+ Ivars.push_back(Iv);
+}
+
+/// DeepCollectObjCIvars -
+/// This routine first collects all declared, but not synthesized, ivars in
+/// super class and then collects all ivars, including those synthesized for
+/// current class. This routine is used for implementation of current class
+/// when all ivars, declared and synthesized are known.
///
-void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
+void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
+ bool leafClass,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
- // Find ivars declared in class extension.
- for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
- CDecl = CDecl->getNextClassExtension()) {
- for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
- E = CDecl->ivar_end(); I != E; ++I) {
- Ivars.push_back(*I);
- }
- }
-
- // Also add any ivar defined in this class's implementation. This
- // includes synthesized ivars.
- if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) {
- for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
- E = ImplDecl->ivar_end(); I != E; ++I)
+ if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
+ DeepCollectObjCIvars(SuperClass, false, Ivars);
+ if (!leafClass) {
+ for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
+ E = OI->ivar_end(); I != E; ++I)
Ivars.push_back(*I);
}
+ else
+ ShallowCollectObjCIvars(OI, Ivars);
}
/// CollectInheritedProtocols - Collect all protocols in current class and
@@ -929,8 +897,10 @@ void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols) {
if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
- PE = OI->protocol_end(); P != PE; ++P) {
+ // We can use protocol_iterator here instead of
+ // all_referenced_protocol_iterator since we are walking all categories.
+ for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(),
+ PE = OI->all_referenced_protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *Proto = (*P);
Protocols.insert(Proto);
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
@@ -950,7 +920,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
SD = SD->getSuperClass();
}
} else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OC->protocol_begin(),
+ for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(),
PE = OC->protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *Proto = (*P);
Protocols.insert(Proto);
@@ -1154,6 +1124,15 @@ static QualType getExtFunctionType(ASTContext& Context, QualType T,
return T;
ResultType = Context.getBlockPointerType(ResultType);
+ } else if (const MemberPointerType *MemberPointer
+ = T->getAs<MemberPointerType>()) {
+ QualType Pointee = MemberPointer->getPointeeType();
+ ResultType = getExtFunctionType(Context, Pointee, Info);
+ if (ResultType == Pointee)
+ return T;
+
+ ResultType = Context.getMemberPointerType(ResultType,
+ MemberPointer->getClass());
} else if (const FunctionType *F = T->getAs<FunctionType>()) {
if (F->getExtInfo() == Info)
return T;
@@ -1570,10 +1549,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
- if (!vecType.isCanonical() || (AltiVecSpec == VectorType::AltiVec)) {
- // pass VectorType::NotAltiVec for AltiVecSpec to make AltiVec canonical
- // vector type (except 'vector bool ...' and 'vector Pixel') the same as
- // the equivalent GCC vector types
+ if (!vecType.isCanonical()) {
Canonical = getVectorType(getCanonicalType(vecType), NumElts,
VectorType::NotAltiVec);
@@ -2567,21 +2543,31 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
return false;
}
-DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
+DeclarationNameInfo ASTContext::getNameForTemplate(TemplateName Name,
+ SourceLocation NameLoc) {
if (TemplateDecl *TD = Name.getAsTemplateDecl())
- return TD->getDeclName();
-
+ // DNInfo work in progress: CHECKME: what about DNLoc?
+ return DeclarationNameInfo(TD->getDeclName(), NameLoc);
+
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+ DeclarationName DName;
if (DTN->isIdentifier()) {
- return DeclarationNames.getIdentifier(DTN->getIdentifier());
+ DName = DeclarationNames.getIdentifier(DTN->getIdentifier());
+ return DeclarationNameInfo(DName, NameLoc);
} else {
- return DeclarationNames.getCXXOperatorName(DTN->getOperator());
+ DName = DeclarationNames.getCXXOperatorName(DTN->getOperator());
+ // DNInfo work in progress: FIXME: source locations?
+ DeclarationNameLoc DNLoc;
+ DNLoc.CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
+ DNLoc.CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
+ return DeclarationNameInfo(DName, NameLoc, DNLoc);
}
}
OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate();
assert(Storage);
- return (*Storage->begin())->getDeclName();
+ // DNInfo work in progress: CHECKME: what about DNLoc?
+ return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc);
}
TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
@@ -3216,14 +3202,14 @@ bool ASTContext::BlockRequiresCopying(QualType Ty) {
return false;
}
-QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
+QualType ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) {
// type = struct __Block_byref_1_X {
// void *__isa;
// struct __Block_byref_1_X *__forwarding;
// unsigned int __flags;
// unsigned int __size;
- // void *__copy_helper; // as needed
- // void *__destroy_help // as needed
+ // void *__copy_helper; // as needed
+ // void *__destroy_help // as needed
// int X;
// } *
@@ -3249,7 +3235,7 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
Ty
};
- const char *FieldNames[] = {
+ llvm::StringRef FieldNames[] = {
"__isa",
"__forwarding",
"__flags",
@@ -3326,7 +3312,7 @@ QualType ASTContext::getBlockParmType(
const ValueDecl *D = BDRE->getDecl();
FieldName = D->getIdentifier();
if (BDRE->isByRef())
- FieldType = BuildByRefType(D->getNameAsCString(), FieldType);
+ FieldType = BuildByRefType(D->getName(), FieldType);
} else {
// Padding.
assert(isa<ConstantArrayType>(FieldType) &&
@@ -3885,15 +3871,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
const IdentifierInfo *II = OI->getIdentifier();
S += II->getName();
S += '=';
- llvm::SmallVector<FieldDecl*, 32> RecFields;
- CollectObjCIvars(OI, RecFields);
- for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
- if (RecFields[i]->isBitField())
- getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true,
- RecFields[i]);
+ llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+ DeepCollectObjCIvars(OI, true, Ivars);
+ for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
+ FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
+ if (Field->isBitField())
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
else
- getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true,
- FD);
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD);
}
S += '}';
return;
@@ -4200,6 +4185,28 @@ static bool areCompatVectorTypes(const VectorType *LHS,
LHS->getNumElements() == RHS->getNumElements();
}
+bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
+ QualType SecondVec) {
+ assert(FirstVec->isVectorType() && "FirstVec should be a vector type");
+ assert(SecondVec->isVectorType() && "SecondVec should be a vector type");
+
+ if (hasSameUnqualifiedType(FirstVec, SecondVec))
+ return true;
+
+ // AltiVec vectors types are identical to equivalent GCC vector types
+ const VectorType *First = FirstVec->getAs<VectorType>();
+ const VectorType *Second = SecondVec->getAs<VectorType>();
+ if ((((First->getAltiVecSpecific() == VectorType::AltiVec) &&
+ (Second->getAltiVecSpecific() == VectorType::NotAltiVec)) ||
+ ((First->getAltiVecSpecific() == VectorType::NotAltiVec) &&
+ (Second->getAltiVecSpecific() == VectorType::AltiVec))) &&
+ hasSameType(First->getElementType(), Second->getElementType()) &&
+ (First->getNumElements() == Second->getNumElements()))
+ return true;
+
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
//===----------------------------------------------------------------------===//
@@ -4226,6 +4233,32 @@ bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
return false;
}
+/// ObjCQualifiedClassTypesAreCompatible - compare Class<p,...> and
+/// Class<p1, ...>.
+bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
+ QualType rhs) {
+ const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+ assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible");
+
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+ E = lhsQID->qual_end(); I != E; ++I) {
+ bool match = false;
+ ObjCProtocolDecl *lhsProto = *I;
+ for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
+ E = rhsOPT->qual_end(); J != E; ++J) {
+ ObjCProtocolDecl *rhsProto = *J;
+ if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ return false;
+ }
+ return true;
+}
+
/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
/// ObjCQualifiedIDType.
bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
@@ -4308,9 +4341,9 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
E = rhsQID->qual_end(); I != E; ++I) {
- // when comparing an id<P> on lhs with a static type on rhs,
- // see if static class implements all of id's protocols, directly or
- // through its super class and categories.
+ // when comparing an id<P> on rhs with a static type on lhs,
+ // static class must implement all of id's protocols directly or
+ // indirectly through its super class.
if (lhsID->ClassImplementsProtocol(*I, true)) {
match = true;
break;
@@ -4365,7 +4398,11 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false);
-
+
+ if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass())
+ return ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0));
+
// If we have 2 user-defined types, fall into that path.
if (LHS->getInterface() && RHS->getInterface())
return canAssignObjCInterfaces(LHS, RHS);
@@ -4541,15 +4578,22 @@ bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
canAssignObjCInterfaces(RHSOPT, LHSOPT);
}
+bool ASTContext::canBindObjCObjectType(QualType To, QualType From) {
+ return canAssignObjCInterfaces(
+ getObjCObjectPointerType(To)->getAs<ObjCObjectPointerType>(),
+ getObjCObjectPointerType(From)->getAs<ObjCObjectPointerType>());
+}
+
/// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
/// both shall have the identically qualified version of a compatible type.
/// C99 6.2.7p1: Two types have compatible types if their types are the
/// same. See 6.7.[2,3,5] for additional rules.
-bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS) {
+bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
+ bool CompareUnqualified) {
if (getLangOptions().CPlusPlus)
return hasSameType(LHS, RHS);
- return !mergeTypes(LHS, RHS).isNull();
+ return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
}
bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) {
@@ -4557,7 +4601,8 @@ bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) {
}
QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
- bool OfBlockPointer) {
+ bool OfBlockPointer,
+ bool Unqualified) {
const FunctionType *lbase = lhs->getAs<FunctionType>();
const FunctionType *rbase = rhs->getAs<FunctionType>();
const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
@@ -4568,13 +4613,26 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
// Check return type
QualType retType;
if (OfBlockPointer)
- retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true);
+ retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true,
+ Unqualified);
else
- retType = mergeTypes(lbase->getResultType(), rbase->getResultType());
+ retType = mergeTypes(lbase->getResultType(), rbase->getResultType(),
+ false, Unqualified);
if (retType.isNull()) return QualType();
- if (getCanonicalType(retType) != getCanonicalType(lbase->getResultType()))
+
+ if (Unqualified)
+ retType = retType.getUnqualifiedType();
+
+ CanQualType LRetType = getCanonicalType(lbase->getResultType());
+ CanQualType RRetType = getCanonicalType(rbase->getResultType());
+ if (Unqualified) {
+ LRetType = LRetType.getUnqualifiedType();
+ RRetType = RRetType.getUnqualifiedType();
+ }
+
+ if (getCanonicalType(retType) != LRetType)
allLTypes = false;
- if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
+ if (getCanonicalType(retType) != RRetType)
allRTypes = false;
// FIXME: double check this
// FIXME: should we error if lbase->getRegParmAttr() != 0 &&
@@ -4619,9 +4677,19 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
for (unsigned i = 0; i < lproto_nargs; i++) {
QualType largtype = lproto->getArgType(i).getUnqualifiedType();
QualType rargtype = rproto->getArgType(i).getUnqualifiedType();
- QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer);
+ QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer,
+ Unqualified);
if (argtype.isNull()) return QualType();
+
+ if (Unqualified)
+ argtype = argtype.getUnqualifiedType();
+
types.push_back(argtype);
+ if (Unqualified) {
+ largtype = largtype.getUnqualifiedType();
+ rargtype = rargtype.getUnqualifiedType();
+ }
+
if (getCanonicalType(argtype) != getCanonicalType(largtype))
allLTypes = false;
if (getCanonicalType(argtype) != getCanonicalType(rargtype))
@@ -4677,7 +4745,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
}
QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
- bool OfBlockPointer) {
+ bool OfBlockPointer,
+ bool Unqualified) {
// C++ [expr]: If an expression initially has the type "reference to T", the
// type is adjusted to "T" prior to any further analysis, the expression
// designates the object or function denoted by the reference, and the
@@ -4685,6 +4754,11 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// the expression is a function call (possibly inside parentheses).
assert(!LHS->getAs<ReferenceType>() && "LHS is a reference type?");
assert(!RHS->getAs<ReferenceType>() && "RHS is a reference type?");
+
+ if (Unqualified) {
+ LHS = LHS.getUnqualifiedType();
+ RHS = RHS.getUnqualifiedType();
+ }
QualType LHSCan = getCanonicalType(LHS),
RHSCan = getCanonicalType(RHS);
@@ -4796,7 +4870,12 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// Merge two pointer types, while trying to preserve typedef info
QualType LHSPointee = LHS->getAs<PointerType>()->getPointeeType();
QualType RHSPointee = RHS->getAs<PointerType>()->getPointeeType();
- QualType ResultType = mergeTypes(LHSPointee, RHSPointee);
+ if (Unqualified) {
+ LHSPointee = LHSPointee.getUnqualifiedType();
+ RHSPointee = RHSPointee.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false,
+ Unqualified);
if (ResultType.isNull()) return QualType();
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
return LHS;
@@ -4809,7 +4888,12 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// Merge two block pointer types, while trying to preserve typedef info
QualType LHSPointee = LHS->getAs<BlockPointerType>()->getPointeeType();
QualType RHSPointee = RHS->getAs<BlockPointerType>()->getPointeeType();
- QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer);
+ if (Unqualified) {
+ LHSPointee = LHSPointee.getUnqualifiedType();
+ RHSPointee = RHSPointee.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,
+ Unqualified);
if (ResultType.isNull()) return QualType();
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
return LHS;
@@ -4826,7 +4910,12 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
QualType LHSElem = getAsArrayType(LHS)->getElementType();
QualType RHSElem = getAsArrayType(RHS)->getElementType();
- QualType ResultType = mergeTypes(LHSElem, RHSElem);
+ if (Unqualified) {
+ LHSElem = LHSElem.getUnqualifiedType();
+ RHSElem = RHSElem.getUnqualifiedType();
+ }
+
+ QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified);
if (ResultType.isNull()) return QualType();
if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
return LHS;
@@ -4860,7 +4949,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
ArrayType::ArraySizeModifier(), 0);
}
case Type::FunctionNoProto:
- return mergeFunctionTypes(LHS, RHS, OfBlockPointer);
+ return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified);
case Type::Record:
case Type::Enum:
return QualType();
@@ -5001,7 +5090,7 @@ unsigned ASTContext::getIntWidth(QualType T) {
}
QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
- assert(T->isSignedIntegerType() && "Unexpected type");
+ assert(T->hasSignedIntegerRepresentation() && "Unexpected type");
// Turn <4 x signed int> -> <4 x unsigned int>
if (const VectorType *VTy = T->getAs<VectorType>())
@@ -5381,8 +5470,8 @@ ASTContext::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
// Finally, we have two differing integer types.
// The rules for this case are in C99 6.3.1.8
int compare = getIntegerTypeOrder(lhs, rhs);
- bool lhsSigned = lhs->isSignedIntegerType(),
- rhsSigned = rhs->isSignedIntegerType();
+ bool lhsSigned = lhs->hasSignedIntegerRepresentation(),
+ rhsSigned = rhs->hasSignedIntegerRepresentation();
QualType destType;
if (lhsSigned == rhsSigned) {
// Same signedness; use the higher-ranked type
@@ -5405,3 +5494,173 @@ ASTContext::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
}
return destType;
}
+
+GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
+ GVALinkage External = GVA_StrongExternal;
+
+ Linkage L = FD->getLinkage();
+ if (L == ExternalLinkage && getLangOptions().CPlusPlus &&
+ FD->getType()->getLinkage() == UniqueExternalLinkage)
+ L = UniqueExternalLinkage;
+
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return GVA_Internal;
+
+ case ExternalLinkage:
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ External = GVA_StrongExternal;
+ break;
+
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ImplicitInstantiation:
+ External = GVA_TemplateInstantiation;
+ break;
+ }
+ }
+
+ if (!FD->isInlined())
+ return External;
+
+ if (!getLangOptions().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
+ // GNU or C99 inline semantics. Determine whether this symbol should be
+ // externally visible.
+ if (FD->isInlineDefinitionExternallyVisible())
+ return External;
+
+ // C99 inline semantics, where the symbol is not externally visible.
+ return GVA_C99Inline;
+ }
+
+ // C++0x [temp.explicit]p9:
+ // [ Note: The intent is that an inline function that is the subject of
+ // an explicit instantiation declaration will still be implicitly
+ // instantiated when used so that the body can be considered for
+ // inlining, but that no out-of-line copy of the inline function would be
+ // generated in the translation unit. -- end note ]
+ if (FD->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration)
+ return GVA_C99Inline;
+
+ return GVA_CXXInline;
+}
+
+GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+ // If this is a static data member, compute the kind of template
+ // specialization. Otherwise, this variable is not part of a
+ // template.
+ TemplateSpecializationKind TSK = TSK_Undeclared;
+ if (VD->isStaticDataMember())
+ TSK = VD->getTemplateSpecializationKind();
+
+ Linkage L = VD->getLinkage();
+ if (L == ExternalLinkage && getLangOptions().CPlusPlus &&
+ VD->getType()->getLinkage() == UniqueExternalLinkage)
+ L = UniqueExternalLinkage;
+
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return GVA_Internal;
+
+ case ExternalLinkage:
+ switch (TSK) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return GVA_StrongExternal;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ llvm_unreachable("Variable should not be instantiated");
+ // Fall through to treat this like any other instantiation.
+
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
+
+ case TSK_ImplicitInstantiation:
+ return GVA_TemplateInstantiation;
+ }
+ }
+
+ return GVA_StrongExternal;
+}
+
+bool ASTContext::DeclMustBeEmitted(const Decl *D) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!VD->isFileVarDecl())
+ return false;
+ } else if (!isa<FunctionDecl>(D))
+ return false;
+
+ // Weak references don't produce any output by themselves.
+ if (D->hasAttr<WeakRefAttr>())
+ return false;
+
+ // Aliases and used decls are required.
+ if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
+ return true;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // Forward declarations aren't required.
+ if (!FD->isThisDeclarationADefinition())
+ return false;
+
+ // Constructors and destructors are required.
+ if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
+ return true;
+
+ // The key function for a class is required.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXRecordDecl *RD = MD->getParent();
+ if (MD->isOutOfLine() && RD->isDynamicClass()) {
+ const CXXMethodDecl *KeyFunc = getKeyFunction(RD);
+ if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl())
+ return true;
+ }
+ }
+
+ GVALinkage Linkage = GetGVALinkageForFunction(FD);
+
+ // static, static inline, always_inline, and extern inline functions can
+ // always be deferred. Normal inline functions can be deferred in C99/C++.
+ // Implicit template instantiations can also be deferred in C++.
+ if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
+ Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
+ return false;
+ return true;
+ }
+
+ const VarDecl *VD = cast<VarDecl>(D);
+ assert(VD->isFileVarDecl() && "Expected file scoped var");
+
+ if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly)
+ return false;
+
+ // Structs that have non-trivial constructors or destructors are required.
+
+ // FIXME: Handle references.
+ if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (RD->hasDefinition() &&
+ (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()))
+ return true;
+ }
+ }
+
+ GVALinkage L = GetGVALinkageForVariable(VD);
+ if (L == GVA_Internal || L == GVA_TemplateInstantiation) {
+ if (!(VD->getInit() && VD->getInit()->HasSideEffects(*this)))
+ return false;
+ }
+
+ return true;
+}
+
+CXXABI::~CXXABI() {}
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 0d609bfa6d39..23f323d0286a 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -151,10 +151,13 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
bool ShouldAKA = false;
QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA);
if (ShouldAKA) {
- S = "'"+S+"' (aka '";
- S += DesugaredTy.getAsString(Context.PrintingPolicy);
- S += "')";
- return S;
+ std::string D = DesugaredTy.getAsString(Context.PrintingPolicy);
+ if (D != S) {
+ S = "'" + S + "' (aka '";
+ S += D;
+ S += "')";
+ return S;
+ }
}
}
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 8d347d171665..2edd09c067e9 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -19,7 +19,6 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
@@ -82,6 +81,8 @@ namespace {
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
SourceLocation &Loc);
+ void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
+ DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC);
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord);
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
@@ -1385,6 +1386,40 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
return false;
}
+void
+ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
+ DeclarationNameInfo& To) {
+ // NOTE: To.Name and To.Loc are already imported.
+ // We only have to import To.LocInfo.
+ switch (To.getName().getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ return;
+
+ case DeclarationName::CXXOperatorName: {
+ SourceRange Range = From.getCXXOperatorNameRange();
+ To.setCXXOperatorNameRange(Importer.Import(Range));
+ return;
+ }
+ case DeclarationName::CXXLiteralOperatorName: {
+ SourceLocation Loc = From.getCXXLiteralOperatorNameLoc();
+ To.setCXXLiteralOperatorNameLoc(Importer.Import(Loc));
+ return;
+ }
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName: {
+ TypeSourceInfo *FromTInfo = From.getNamedTypeInfo();
+ To.setNamedTypeInfo(Importer.Import(FromTInfo));
+ return;
+ }
+ assert(0 && "Unknown name kind.");
+ }
+}
+
void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC) {
for (DeclContext::decl_iterator From = FromDC->decls_begin(),
FromEnd = FromDC->decls_end();
@@ -1752,7 +1787,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Base1->isVirtual(),
Base1->isBaseOfClass(),
Base1->getAccessSpecifierAsWritten(),
- T));
+ Importer.Import(Base1->getTypeSourceInfo())));
}
if (!Bases.empty())
D2CXX->setBases(Bases.data(), Bases.size());
@@ -1822,7 +1857,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
return 0;
-
+
// Try to find a function in our own ("to") context with the same name, same
// type, and in the same context as the function we're importing.
if (!LexicalDC->isFunctionOrMethod()) {
@@ -1871,6 +1906,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
}
+ DeclarationNameInfo NameInfo(Name, Loc);
+ // Import additional name location/type info.
+ ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
@@ -1893,26 +1932,26 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- Loc, Name, T, TInfo,
+ NameInfo, T, TInfo,
FromConstructor->isExplicit(),
D->isInlineSpecified(),
D->isImplicit());
} else if (isa<CXXDestructorDecl>(D)) {
ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- Loc, Name, T,
+ NameInfo, T,
D->isInlineSpecified(),
D->isImplicit());
} else if (CXXConversionDecl *FromConversion
= dyn_cast<CXXConversionDecl>(D)) {
ToFunction = CXXConversionDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- Loc, Name, T, TInfo,
+ NameInfo, T, TInfo,
D->isInlineSpecified(),
FromConversion->isExplicit());
} else {
- ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, Loc,
- Name, T, TInfo, D->getStorageClass(),
+ ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
+ NameInfo, T, TInfo, D->getStorageClass(),
D->getStorageClassAsWritten(),
D->isInlineSpecified(),
D->hasWrittenPrototype());
@@ -2026,7 +2065,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
cast<ObjCContainerDecl>(DC),
Loc, Name.getAsIdentifierInfo(),
T, TInfo, D->getAccessControl(),
- BitWidth);
+ BitWidth, D->getSynthesize());
ToIvar->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToIvar);
LexicalDC->addDecl(ToIvar);
@@ -2299,6 +2338,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
D->isInstanceMethod(),
D->isVariadic(),
D->isSynthesized(),
+ D->isDefined(),
D->getImplementationControl());
// FIXME: When we decide to merge method definitions, we'll need to
@@ -2513,6 +2553,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
ObjCInterfaceDecl::protocol_loc_iterator
FromProtoLoc = D->protocol_loc_begin();
+
+ // FIXME: Should we be usng all_referenced_protocol_begin() here?
for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
FromProtoEnd = D->protocol_end();
FromProto != FromProtoEnd;
@@ -2778,8 +2820,9 @@ Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
if (T.isNull())
return 0;
- return new (Importer.getToContext())
- IntegerLiteral(E->getValue(), T, Importer.Import(E->getLocation()));
+ return IntegerLiteral::Create(Importer.getToContext(),
+ E->getValue(), T,
+ Importer.Import(E->getLocation()));
}
Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
@@ -2886,6 +2929,13 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
Importer.Import(E->getOperatorLoc()));
}
+bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
+ if (E->path_empty()) return false;
+
+ // TODO: import cast paths
+ return true;
+}
+
Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -2894,13 +2944,13 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr)
return 0;
-
- // FIXME: Initialize the base path.
- assert(E->getBasePath().empty() && "FIXME: Must copy base path!");
- CXXBaseSpecifierArray BasePath;
- return new (Importer.getToContext()) ImplicitCastExpr(T, E->getCastKind(),
- SubExpr, BasePath,
- E->isLvalueCast());
+
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return 0;
+
+ return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+ SubExpr, &BasePath, E->getValueKind());
}
Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
@@ -2916,13 +2966,14 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
if (!TInfo && E->getTypeInfoAsWritten())
return 0;
- // FIXME: Initialize the base path.
- assert(E->getBasePath().empty() && "FIXME: Must copy base path!");
- CXXBaseSpecifierArray BasePath;
- return new (Importer.getToContext()) CStyleCastExpr(T, E->getCastKind(),
- SubExpr, BasePath, TInfo,
- Importer.Import(E->getLParenLoc()),
- Importer.Import(E->getRParenLoc()));
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return 0;
+
+ return CStyleCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ Importer.Import(E->getLParenLoc()),
+ Importer.Import(E->getRParenLoc()));
}
ASTImporter::ASTImporter(Diagnostic &Diags,
@@ -2964,8 +3015,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
return FromTSI;
// FIXME: For now we just create a "trivial" type source info based
- // on the type and a seingle location. Implement a real version of
- // this.
+ // on the type and a single location. Implement a real version of this.
QualType T = Import(FromTSI->getType());
if (T.isNull())
return 0;
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
index b09ba895c019..3ca7d4d01d1c 100644
--- a/lib/AST/AttrImpl.cpp
+++ b/lib/AST/AttrImpl.cpp
@@ -13,198 +13,10 @@
#include "clang/AST/Attr.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Expr.h"
using namespace clang;
-void Attr::Destroy(ASTContext &C) {
- if (Next) {
- Next->Destroy(C);
- Next = 0;
- }
- this->~Attr();
- C.Deallocate((void*)this);
-}
+Attr::~Attr() { }
-AttrWithString::AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s)
- : Attr(AK) {
- assert(!s.empty());
- StrLen = s.size();
- Str = new (C) char[StrLen];
- memcpy(const_cast<char*>(Str), s.data(), StrLen);
-}
-
-void AttrWithString::Destroy(ASTContext &C) {
- C.Deallocate(const_cast<char*>(Str));
- Attr::Destroy(C);
-}
-
-void AttrWithString::ReplaceString(ASTContext &C, llvm::StringRef newS) {
- if (newS.size() > StrLen) {
- C.Deallocate(const_cast<char*>(Str));
- Str = new (C) char[newS.size()];
- }
- StrLen = newS.size();
- memcpy(const_cast<char*>(Str), newS.data(), StrLen);
-}
-
-void FormatAttr::setType(ASTContext &C, llvm::StringRef type) {
- ReplaceString(C, type);
-}
-
-NonNullAttr::NonNullAttr(ASTContext &C, unsigned* arg_nums, unsigned size)
- : Attr(attr::NonNull), ArgNums(0), Size(0) {
- if (size == 0)
- return;
- assert(arg_nums);
- ArgNums = new (C) unsigned[size];
- Size = size;
- memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
-}
-
-void NonNullAttr::Destroy(ASTContext &C) {
- if (ArgNums)
- C.Deallocate(ArgNums);
- Attr::Destroy(C);
-}
-
-#define DEF_SIMPLE_ATTR_CLONE(ATTR) \
- Attr *ATTR##Attr::clone(ASTContext &C) const { \
- return ::new (C) ATTR##Attr; \
- }
-
-// FIXME: Can we use variadic macro to define DEF_SIMPLE_ATTR_CLONE for
-// "non-simple" classes?
-
-DEF_SIMPLE_ATTR_CLONE(AlignMac68k)
-DEF_SIMPLE_ATTR_CLONE(AlwaysInline)
-DEF_SIMPLE_ATTR_CLONE(AnalyzerNoReturn)
-DEF_SIMPLE_ATTR_CLONE(BaseCheck)
-DEF_SIMPLE_ATTR_CLONE(CDecl)
-DEF_SIMPLE_ATTR_CLONE(CFReturnsNotRetained)
-DEF_SIMPLE_ATTR_CLONE(CFReturnsRetained)
-DEF_SIMPLE_ATTR_CLONE(Const)
-DEF_SIMPLE_ATTR_CLONE(DLLExport)
-DEF_SIMPLE_ATTR_CLONE(DLLImport)
-DEF_SIMPLE_ATTR_CLONE(Deprecated)
-DEF_SIMPLE_ATTR_CLONE(FastCall)
-DEF_SIMPLE_ATTR_CLONE(Final)
-DEF_SIMPLE_ATTR_CLONE(Hiding)
-DEF_SIMPLE_ATTR_CLONE(Malloc)
-DEF_SIMPLE_ATTR_CLONE(NSReturnsNotRetained)
-DEF_SIMPLE_ATTR_CLONE(NSReturnsRetained)
-DEF_SIMPLE_ATTR_CLONE(NoDebug)
-DEF_SIMPLE_ATTR_CLONE(NoInline)
-DEF_SIMPLE_ATTR_CLONE(NoInstrumentFunction)
-DEF_SIMPLE_ATTR_CLONE(NoReturn)
-DEF_SIMPLE_ATTR_CLONE(NoThrow)
-DEF_SIMPLE_ATTR_CLONE(ObjCException)
-DEF_SIMPLE_ATTR_CLONE(ObjCNSObject)
-DEF_SIMPLE_ATTR_CLONE(Override)
-DEF_SIMPLE_ATTR_CLONE(Packed)
-DEF_SIMPLE_ATTR_CLONE(Pure)
-DEF_SIMPLE_ATTR_CLONE(StdCall)
-DEF_SIMPLE_ATTR_CLONE(ThisCall)
-DEF_SIMPLE_ATTR_CLONE(TransparentUnion)
-DEF_SIMPLE_ATTR_CLONE(Unavailable)
-DEF_SIMPLE_ATTR_CLONE(Unused)
-DEF_SIMPLE_ATTR_CLONE(Used)
-DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult)
-DEF_SIMPLE_ATTR_CLONE(Weak)
-DEF_SIMPLE_ATTR_CLONE(WeakImport)
-DEF_SIMPLE_ATTR_CLONE(WeakRef)
-DEF_SIMPLE_ATTR_CLONE(X86ForceAlignArgPointer)
-
-Attr* MaxFieldAlignmentAttr::clone(ASTContext &C) const {
- return ::new (C) MaxFieldAlignmentAttr(Alignment);
-}
-
-Attr* AlignedAttr::clone(ASTContext &C) const {
- return ::new (C) AlignedAttr(Alignment);
-}
-
-Attr* AnnotateAttr::clone(ASTContext &C) const {
- return ::new (C) AnnotateAttr(C, getAnnotation());
-}
-
-Attr *AsmLabelAttr::clone(ASTContext &C) const {
- return ::new (C) AsmLabelAttr(C, getLabel());
-}
-
-Attr *AliasAttr::clone(ASTContext &C) const {
- return ::new (C) AliasAttr(C, getAliasee());
-}
-
-Attr *ConstructorAttr::clone(ASTContext &C) const {
- return ::new (C) ConstructorAttr(priority);
-}
-
-Attr *DestructorAttr::clone(ASTContext &C) const {
- return ::new (C) DestructorAttr(priority);
-}
-
-Attr *IBOutletAttr::clone(ASTContext &C) const {
- return ::new (C) IBOutletAttr;
-}
-
-Attr *IBOutletCollectionAttr::clone(ASTContext &C) const {
- return ::new (C) IBOutletCollectionAttr(D);
-}
-
-Attr *IBActionAttr::clone(ASTContext &C) const {
- return ::new (C) IBActionAttr;
-}
-
-Attr *GNUInlineAttr::clone(ASTContext &C) const {
- return ::new (C) GNUInlineAttr;
-}
-
-Attr *SectionAttr::clone(ASTContext &C) const {
- return ::new (C) SectionAttr(C, getName());
-}
-
-Attr *NonNullAttr::clone(ASTContext &C) const {
- return ::new (C) NonNullAttr(C, ArgNums, Size);
-}
-
-Attr *FormatAttr::clone(ASTContext &C) const {
- return ::new (C) FormatAttr(C, getType(), formatIdx, firstArg);
-}
-
-Attr *FormatArgAttr::clone(ASTContext &C) const {
- return ::new (C) FormatArgAttr(formatIdx);
-}
-
-Attr *SentinelAttr::clone(ASTContext &C) const {
- return ::new (C) SentinelAttr(sentinel, NullPos);
-}
-
-Attr *VisibilityAttr::clone(ASTContext &C) const {
- return ::new (C) VisibilityAttr(VisibilityType);
-}
-
-Attr *OverloadableAttr::clone(ASTContext &C) const {
- return ::new (C) OverloadableAttr;
-}
-
-Attr *BlocksAttr::clone(ASTContext &C) const {
- return ::new (C) BlocksAttr(BlocksAttrType);
-}
-
-Attr *CleanupAttr::clone(ASTContext &C) const {
- return ::new (C) CleanupAttr(FD);
-}
-
-Attr *RegparmAttr::clone(ASTContext &C) const {
- return ::new (C) RegparmAttr(NumParams);
-}
-
-Attr *ReqdWorkGroupSizeAttr::clone(ASTContext &C) const {
- return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
-}
-
-Attr *InitPriorityAttr::clone(ASTContext &C) const {
- return ::new (C) InitPriorityAttr(Priority);
-}
-
-Attr *MSP430InterruptAttr::clone(ASTContext &C) const {
- return ::new (C) MSP430InterruptAttr(Number);
-}
+#include "clang/AST/AttrImpl.inc"
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 407ed95f3ee1..82a81ec42411 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -23,6 +23,8 @@ add_clang_library(clangAST
ExprCXX.cpp
FullExpr.cpp
InheritViz.cpp
+ ItaniumCXXABI.cpp
+ MicrosoftCXXABI.cpp
NestedNameSpecifier.cpp
ParentMap.cpp
RecordLayout.cpp
@@ -41,4 +43,4 @@ add_clang_library(clangAST
)
add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList
- ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
+ ClangAttrImpl ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h
new file mode 100644
index 000000000000..4b38d7afb6a4
--- /dev/null
+++ b/lib/AST/CXXABI.h
@@ -0,0 +1,39 @@
+//===----- CXXABI.h - Interface to C++ ABIs ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for C++ AST support. Concrete
+// subclasses of this implement AST support for specific C++ ABIs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CXXABI_H
+#define LLVM_CLANG_AST_CXXABI_H
+
+namespace clang {
+
+class ASTContext;
+class MemberPointerType;
+
+/// Implements C++ ABI-specific semantic analysis functions.
+class CXXABI {
+public:
+ virtual ~CXXABI();
+
+ /// Returns the size of a member pointer in multiples of the target
+ /// pointer size.
+ virtual unsigned getMemberPointerSize(const MemberPointerType *MPT) const = 0;
+};
+
+/// Creates an instance of a C++ ABI class.
+CXXABI *CreateARMCXXABI(ASTContext &Ctx);
+CXXABI *CreateItaniumCXXABI(ASTContext &Ctx);
+CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx);
+}
+
+#endif
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 149938fc5c86..b7be02d74533 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -97,8 +97,14 @@ static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args,
return L;
}
+static Linkage
+getLinkageForTemplateArgumentList(const TemplateArgumentList &TArgs) {
+ return getLinkageForTemplateArgumentList(TArgs.getFlatArgumentList(),
+ TArgs.flat_size());
+}
+
static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
- assert(D->getDeclContext()->getLookupContext()->isFileContext() &&
+ assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
@@ -110,7 +116,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// (This bullet corresponds to C99 6.2.2p3.)
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
- if (Var->getStorageClass() == VarDecl::Static)
+ if (Var->getStorageClass() == SC_Static)
return InternalLinkage;
// - an object or reference that is explicitly declared const
@@ -119,8 +125,8 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// (there is no equivalent in C99)
if (Context.getLangOptions().CPlusPlus &&
Var->getType().isConstant(Context) &&
- Var->getStorageClass() != VarDecl::Extern &&
- Var->getStorageClass() != VarDecl::PrivateExtern) {
+ Var->getStorageClass() != SC_Extern &&
+ Var->getStorageClass() != SC_PrivateExtern) {
bool FoundExtern = false;
for (const VarDecl *PrevVar = Var->getPreviousDeclaration();
PrevVar && !FoundExtern;
@@ -143,7 +149,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
Function = cast<FunctionDecl>(D);
// Explicitly declared static.
- if (Function->getStorageClass() == FunctionDecl::Static)
+ if (Function->getStorageClass() == SC_Static)
return InternalLinkage;
} else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
// - a data member of an anonymous union.
@@ -159,8 +165,8 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// - an object or reference, unless it has internal linkage; or
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (!Context.getLangOptions().CPlusPlus &&
- (Var->getStorageClass() == VarDecl::Extern ||
- Var->getStorageClass() == VarDecl::PrivateExtern)) {
+ (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
@@ -194,9 +200,9 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// as if it were declared with the storage-class specifier
// extern.
if (!Context.getLangOptions().CPlusPlus &&
- (Function->getStorageClass() == FunctionDecl::Extern ||
- Function->getStorageClass() == FunctionDecl::PrivateExtern ||
- Function->getStorageClass() == FunctionDecl::None)) {
+ (Function->getStorageClass() == SC_Extern ||
+ Function->getStorageClass() == SC_PrivateExtern ||
+ Function->getStorageClass() == SC_None)) {
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
@@ -219,10 +225,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
= Function->getTemplateSpecializationInfo()) {
Linkage L = SpecInfo->getTemplate()->getLinkage();
const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
- L = minLinkage(L,
- getLinkageForTemplateArgumentList(
- TemplateArgs.getFlatArgumentList(),
- TemplateArgs.flat_size()));
+ L = minLinkage(L, getLinkageForTemplateArgumentList(TemplateArgs));
return L;
}
@@ -245,9 +248,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- Linkage L = getLinkageForTemplateArgumentList(
- TemplateArgs.getFlatArgumentList(),
- TemplateArgs.flat_size());
+ Linkage L = getLinkageForTemplateArgumentList(TemplateArgs);
return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
}
@@ -279,6 +280,47 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
return NoLinkage;
}
+static Linkage getLinkageForClassMember(const NamedDecl *D) {
+ if (!(isa<CXXMethodDecl>(D) ||
+ isa<VarDecl>(D) ||
+ (isa<TagDecl>(D) &&
+ (D->getDeclName() || cast<TagDecl>(D)->getTypedefForAnonDecl()))))
+ return NoLinkage;
+
+ // Class members only have linkage if their class has external linkage.
+ Linkage L = cast<RecordDecl>(D->getDeclContext())->getLinkage();
+ if (!isExternalLinkage(L)) return NoLinkage;
+
+ // If the class already has unique-external linkage, we can't improve.
+ if (L == UniqueExternalLinkage) return UniqueExternalLinkage;
+
+ // If this is a method template specialization, use the linkage for
+ // the template parameters and arguments.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (FunctionTemplateSpecializationInfo *SpecInfo
+ = MD->getTemplateSpecializationInfo()) {
+ Linkage ArgLinkage =
+ getLinkageForTemplateArgumentList(*SpecInfo->TemplateArguments);
+ Linkage ParamLinkage =
+ getLinkageForTemplateParameterList(
+ SpecInfo->getTemplate()->getTemplateParameters());
+ return minLinkage(ArgLinkage, ParamLinkage);
+ }
+
+ // Similarly for member class template specializations.
+ } else if (const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ Linkage ArgLinkage =
+ getLinkageForTemplateArgumentList(Spec->getTemplateArgs());
+ Linkage ParamLinkage =
+ getLinkageForTemplateParameterList(
+ Spec->getSpecializedTemplate()->getTemplateParameters());
+ return minLinkage(ArgLinkage, ParamLinkage);
+ }
+
+ return ExternalLinkage;
+}
+
Linkage NamedDecl::getLinkage() const {
// Objective-C: treat all Objective-C declarations as having external
@@ -303,7 +345,7 @@ Linkage NamedDecl::getLinkage() const {
}
// Handle linkage for namespace-scope names.
- if (getDeclContext()->getLookupContext()->isFileContext())
+ if (getDeclContext()->getRedeclContext()->isFileContext())
if (Linkage L = getLinkageForNamespaceScopeDecl(this))
return L;
@@ -314,14 +356,8 @@ Linkage NamedDecl::getLinkage() const {
// that the class or enumeration has the typedef name for linkage
// purposes (7.1.3), has external linkage if the name of the class
// has external linkage.
- if (getDeclContext()->isRecord() &&
- (isa<CXXMethodDecl>(this) || isa<VarDecl>(this) ||
- (isa<TagDecl>(this) &&
- (getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl())))) {
- Linkage L = cast<RecordDecl>(getDeclContext())->getLinkage();
- if (isExternalLinkage(L))
- return L;
- }
+ if (getDeclContext()->isRecord())
+ return getLinkageForClassMember(this);
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
@@ -347,8 +383,8 @@ Linkage NamedDecl::getLinkage() const {
}
if (const VarDecl *Var = dyn_cast<VarDecl>(this))
- if (Var->getStorageClass() == VarDecl::Extern ||
- Var->getStorageClass() == VarDecl::PrivateExtern) {
+ if (Var->getStorageClass() == SC_Extern ||
+ Var->getStorageClass() == SC_PrivateExtern) {
if (Var->getPreviousDeclaration())
if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
return L;
@@ -531,13 +567,6 @@ static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
return decl->getInnerLocStart();
}
-DeclaratorDecl::~DeclaratorDecl() {}
-void DeclaratorDecl::Destroy(ASTContext &C) {
- if (hasExtInfo())
- C.Deallocate(getExtInfo());
- ValueDecl::Destroy(C);
-}
-
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
TypeSourceInfo *TSI = getTypeSourceInfo();
if (TSI) return TSI->getTypeLoc().getBeginLoc();
@@ -602,24 +631,18 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
}
}
-void QualifierInfo::Destroy(ASTContext &Context) {
- // FIXME: Deallocate template parameter lists themselves!
- if (TemplParamLists)
- Context.Deallocate(TemplParamLists);
-}
-
//===----------------------------------------------------------------------===//
// VarDecl Implementation
//===----------------------------------------------------------------------===//
const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
switch (SC) {
- case VarDecl::None: break;
- case VarDecl::Auto: return "auto"; break;
- case VarDecl::Extern: return "extern"; break;
- case VarDecl::PrivateExtern: return "__private_extern__"; break;
- case VarDecl::Register: return "register"; break;
- case VarDecl::Static: return "static"; break;
+ case SC_None: break;
+ case SC_Auto: return "auto"; break;
+ case SC_Extern: return "extern"; break;
+ case SC_PrivateExtern: return "__private_extern__"; break;
+ case SC_Register: return "register"; break;
+ case SC_Static: return "static"; break;
}
assert(0 && "Invalid storage class");
@@ -632,22 +655,6 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten);
}
-void VarDecl::Destroy(ASTContext& C) {
- Expr *Init = getInit();
- if (Init) {
- Init->Destroy(C);
- if (EvaluatedStmt *Eval = this->Init.dyn_cast<EvaluatedStmt *>()) {
- Eval->~EvaluatedStmt();
- C.Deallocate(Eval);
- }
- }
- this->~VarDecl();
- DeclaratorDecl::Destroy(C);
-}
-
-VarDecl::~VarDecl() {
-}
-
SourceLocation VarDecl::getInnerLocStart() const {
SourceLocation Start = getTypeSpecStartLoc();
if (Start.isInvalid())
@@ -665,14 +672,14 @@ bool VarDecl::isExternC() const {
ASTContext &Context = getASTContext();
if (!Context.getLangOptions().CPlusPlus)
return (getDeclContext()->isTranslationUnit() &&
- getStorageClass() != Static) ||
+ getStorageClass() != SC_Static) ||
(getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
- return getStorageClass() != Static;
+ return getStorageClass() != SC_Static;
break;
}
@@ -717,8 +724,8 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
if (hasExternalStorage())
return DeclarationOnly;
- if (getStorageClassAsWritten() == Extern ||
- getStorageClassAsWritten() == PrivateExtern) {
+ if (getStorageClassAsWritten() == SC_Extern ||
+ getStorageClassAsWritten() == SC_PrivateExtern) {
for (const VarDecl *PrevVar = getPreviousDeclaration();
PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) {
if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit())
@@ -912,28 +919,6 @@ SourceRange ParmVarDecl::getDefaultArgRange() const {
// FunctionDecl Implementation
//===----------------------------------------------------------------------===//
-void FunctionDecl::Destroy(ASTContext& C) {
- if (Body && Body.isOffset())
- Body.get(C.getExternalSource())->Destroy(C);
-
- for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
- (*I)->Destroy(C);
-
- FunctionTemplateSpecializationInfo *FTSInfo
- = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
- if (FTSInfo)
- C.Deallocate(FTSInfo);
-
- MemberSpecializationInfo *MSInfo
- = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
- if (MSInfo)
- C.Deallocate(MSInfo);
-
- C.Deallocate(ParamInfo);
-
- DeclaratorDecl::Destroy(C);
-}
-
void FunctionDecl::getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const {
@@ -984,7 +969,7 @@ void FunctionDecl::setBody(Stmt *B) {
bool FunctionDecl::isMain() const {
ASTContext &Context = getASTContext();
return !Context.getLangOptions().Freestanding &&
- getDeclContext()->getLookupContext()->isTranslationUnit() &&
+ getDeclContext()->getRedeclContext()->isTranslationUnit() &&
getIdentifier() && getIdentifier()->isStr("main");
}
@@ -993,17 +978,20 @@ bool FunctionDecl::isExternC() const {
// In C, any non-static, non-overloadable function has external
// linkage.
if (!Context.getLangOptions().CPlusPlus)
- return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+ return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>();
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
- return getStorageClass() != Static &&
+ return getStorageClass() != SC_Static &&
!getAttr<OverloadableAttr>();
break;
}
+
+ if (DC->isRecord())
+ break;
}
return false;
@@ -1013,7 +1001,7 @@ bool FunctionDecl::isGlobal() const {
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
return Method->isStatic();
- if (getStorageClass() == Static)
+ if (getStorageClass() == SC_Static)
return false;
for (const DeclContext *DC = getDeclContext();
@@ -1072,7 +1060,7 @@ unsigned FunctionDecl::getBuiltinID() const {
// function or whether it just has the same name.
// If this is a static function, it's not a builtin.
- if (getStorageClass() == Static)
+ if (getStorageClass() == SC_Static)
return 0;
// If this function is at translation-unit scope and we're not in
@@ -1206,7 +1194,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
Redecl != RedeclEnd;
++Redecl) {
- if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != Extern)
+ if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != SC_Extern)
return true;
}
@@ -1225,7 +1213,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
continue;
- if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == Extern)
+ if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
return true; // Not an inline definition
}
@@ -1400,14 +1388,15 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
if (InsertPos)
Template->getSpecializations().InsertNode(Info, InsertPos);
else {
- // Try to insert the new node. If there is an existing node, remove it
- // first.
+ // Try to insert the new node. If there is an existing node, leave it, the
+ // set will contain the canonical decls while
+ // FunctionTemplateDecl::findSpecialization will return
+ // the most recent redeclarations.
FunctionTemplateSpecializationInfo *Existing
= Template->getSpecializations().GetOrInsertNode(Info);
- if (Existing) {
- Template->getSpecializations().RemoveNode(Existing);
- Template->getSpecializations().GetOrInsertNode(Info);
- }
+ (void)Existing;
+ assert((!Existing || Existing->Function->isCanonicalDecl()) &&
+ "Set is supposed to only contain canonical decls");
}
}
@@ -1564,12 +1553,6 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
// TagDecl Implementation
//===----------------------------------------------------------------------===//
-void TagDecl::Destroy(ASTContext &C) {
- if (hasExtInfo())
- C.Deallocate(getExtInfo());
- TypeDecl::Destroy(C);
-}
-
SourceLocation TagDecl::getOuterLocStart() const {
return getTemplateOrInnerLocStart(this);
}
@@ -1590,14 +1573,7 @@ void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) {
}
void TagDecl::startDefinition() {
- if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
- TagT->decl.setPointer(this);
- TagT->decl.setInt(1);
- } else if (InjectedClassNameType *Injected
- = const_cast<InjectedClassNameType *>(
- TypeForDecl->getAs<InjectedClassNameType>())) {
- Injected->Decl = cast<CXXRecordDecl>(this);
- }
+ IsBeingDefined = true;
if (isa<CXXRecordDecl>(this)) {
CXXRecordDecl *D = cast<CXXRecordDecl>(this);
@@ -1614,17 +1590,7 @@ void TagDecl::completeDefinition() {
"definition completed but not started");
IsDefinition = true;
- if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
- assert(TagT->decl.getPointer() == this &&
- "Attempt to redefine a tag definition?");
- TagT->decl.setInt(0);
- } else if (InjectedClassNameType *Injected
- = const_cast<InjectedClassNameType *>(
- TypeForDecl->getAs<InjectedClassNameType>())) {
- assert(Injected->Decl == this &&
- "Attempt to redefine a class template definition?");
- (void)Injected;
- }
+ IsBeingDefined = false;
}
TagDecl* TagDecl::getDefinition() const {
@@ -1675,10 +1641,6 @@ EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) {
return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation());
}
-void EnumDecl::Destroy(ASTContext& C) {
- TagDecl::Destroy(C);
-}
-
void EnumDecl::completeDefinition(QualType NewType,
QualType NewPromotionType,
unsigned NumPositiveBits,
@@ -1719,13 +1681,6 @@ RecordDecl *RecordDecl::Create(ASTContext &C, EmptyShell Empty) {
SourceLocation());
}
-RecordDecl::~RecordDecl() {
-}
-
-void RecordDecl::Destroy(ASTContext& C) {
- TagDecl::Destroy(C);
-}
-
bool RecordDecl::isInjectedClassName() const {
return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
@@ -1753,20 +1708,6 @@ ValueDecl *RecordDecl::getAnonymousStructOrUnionObject() {
// BlockDecl Implementation
//===----------------------------------------------------------------------===//
-BlockDecl::~BlockDecl() {
-}
-
-void BlockDecl::Destroy(ASTContext& C) {
- if (Body)
- Body->Destroy(C);
-
- for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
- (*I)->Destroy(C);
-
- C.Deallocate(ParamInfo);
- Decl::Destroy(C);
-}
-
void BlockDecl::setParams(ParmVarDecl **NewParamInfo,
unsigned NParms) {
assert(ParamInfo == 0 && "Already has param info!");
@@ -1798,27 +1739,17 @@ NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) NamespaceDecl(DC, L, Id);
}
-void NamespaceDecl::Destroy(ASTContext& C) {
- // NamespaceDecl uses "NextDeclarator" to chain namespace declarations
- // together. They are all top-level Decls.
-
- this->~NamespaceDecl();
- Decl::Destroy(C);
-}
-
-
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, QualType T) {
return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T);
}
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- DeclarationName N, QualType T,
- TypeSourceInfo *TInfo,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten,
bool isInline, bool hasWrittenPrototype) {
- FunctionDecl *New = new (C) FunctionDecl(Function, DC, L, N, T, TInfo,
+ FunctionDecl *New = new (C) FunctionDecl(Function, DC, NameInfo, T, TInfo,
S, SCAsWritten, isInline);
New->HasWrittenPrototype = hasWrittenPrototype;
return New;
@@ -1835,9 +1766,11 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
return new (C) EnumConstantDecl(CD, L, Id, T, E, V);
}
-void EnumConstantDecl::Destroy(ASTContext& C) {
- if (Init) Init->Destroy(C);
- ValueDecl::Destroy(C);
+SourceRange EnumConstantDecl::getSourceRange() const {
+ SourceLocation End = getLocation();
+ if (Init)
+ End = Init->getLocEnd();
+ return SourceRange(getLocation(), End);
}
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
@@ -1846,9 +1779,6 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TypedefDecl(DC, L, Id, TInfo);
}
-// Anchor TypedefDecl's vtable here.
-TypedefDecl::~TypedefDecl() {}
-
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
StringLiteral *Str) {
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index d4f997de7669..0b958fe82b09 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -157,9 +157,7 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
//===----------------------------------------------------------------------===//
// Out-of-line virtual method providing a home for Decl.
-Decl::~Decl() {
- assert(!HasAttrs && "attributes should have been freed by Destroy");
-}
+Decl::~Decl() { }
void Decl::setDeclContext(DeclContext *DC) {
if (isOutOfSemaDC())
@@ -314,35 +312,25 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
return 0;
}
-void Decl::initAttrs(Attr *attrs) {
+void Decl::setAttrs(const AttrVec &attrs) {
assert(!HasAttrs && "Decl already contains attrs.");
- Attr *&AttrBlank = getASTContext().getDeclAttrs(this);
- assert(AttrBlank == 0 && "HasAttrs was wrong?");
+ AttrVec &AttrBlank = getASTContext().getDeclAttrs(this);
+ assert(AttrBlank.empty() && "HasAttrs was wrong?");
AttrBlank = attrs;
HasAttrs = true;
}
-void Decl::addAttr(Attr *NewAttr) {
- Attr *&ExistingAttr = getASTContext().getDeclAttrs(this);
-
- assert(NewAttr->getNext() == 0 && "Chain of attributes will be truncated!");
- NewAttr->setNext(ExistingAttr);
- ExistingAttr = NewAttr;
-
- HasAttrs = true;
-}
-
-void Decl::invalidateAttrs() {
+void Decl::dropAttrs() {
if (!HasAttrs) return;
HasAttrs = false;
getASTContext().eraseDeclAttrs(this);
}
-const Attr *Decl::getAttrsImpl() const {
- assert(HasAttrs && "getAttrs() should verify this!");
+const AttrVec &Decl::getAttrs() const {
+ assert(HasAttrs && "No attrs to get!");
return getASTContext().getDeclAttrs(this);
}
@@ -372,40 +360,6 @@ void Decl::swapAttrs(Decl *RHS) {
RHS->HasAttrs = true;
}
-void Decl::Destroy(ASTContext &C) {
- // Free attributes for this decl.
- if (HasAttrs) {
- C.getDeclAttrs(this)->Destroy(C);
- invalidateAttrs();
- HasAttrs = false;
- }
-
-#if 0
- // FIXME: Once ownership is fully understood, we can enable this code
- if (DeclContext *DC = dyn_cast<DeclContext>(this))
- DC->decls_begin()->Destroy(C);
-
- // Observe the unrolled recursion. By setting N->NextDeclInContext = 0x0
- // within the loop, only the Destroy method for the first Decl
- // will deallocate all of the Decls in a chain.
-
- Decl* N = getNextDeclInContext();
-
- while (N) {
- Decl* Tmp = N->getNextDeclInContext();
- N->NextDeclInContext = 0;
- N->Destroy(C);
- N = Tmp;
- }
-
- if (isOutOfSemaDC())
- delete (C) getMultipleDC();
-
- this->~Decl();
- C.Deallocate((void *)this);
-#endif
-}
-
Decl *Decl::castFromDeclContext (const DeclContext *D) {
Decl::Kind DK = D->getDeclKind();
switch(DK) {
@@ -506,17 +460,7 @@ bool DeclContext::classof(const Decl *D) {
}
}
-DeclContext::~DeclContext() {
- // FIXME: Currently ~ASTContext will delete the StoredDeclsMaps because
- // ~DeclContext() is not guaranteed to be called when ASTContext uses
- // a BumpPtrAllocator.
- // delete LookupPtr;
-}
-
-void DeclContext::DestroyDecls(ASTContext &C) {
- for (decl_iterator D = decls_begin(); D != decls_end(); )
- (*D++)->Destroy(C);
-}
+DeclContext::~DeclContext() { }
/// \brief Find the parent context of this context that will be
/// used for unqualified name lookup.
@@ -527,13 +471,18 @@ void DeclContext::DestroyDecls(ASTContext &C) {
DeclContext *DeclContext::getLookupParent() {
// FIXME: Find a better way to identify friends
if (isa<FunctionDecl>(this))
- if (getParent()->getLookupContext()->isFileContext() &&
- getLexicalParent()->getLookupContext()->isRecord())
+ if (getParent()->getRedeclContext()->isFileContext() &&
+ getLexicalParent()->getRedeclContext()->isRecord())
return getLexicalParent();
return getParent();
}
+bool DeclContext::isInlineNamespace() const {
+ return isNamespace() &&
+ cast<NamespaceDecl>(this)->isInline();
+}
+
bool DeclContext::isDependentContext() const {
if (isFileContext())
return false;
@@ -565,13 +514,11 @@ bool DeclContext::isTransparentContext() const {
return true;
else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord)
return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
- else if (DeclKind == Decl::Namespace)
- return false; // FIXME: Check for C++0x inline namespaces
return false;
}
-bool DeclContext::Encloses(DeclContext *DC) {
+bool DeclContext::Encloses(const DeclContext *DC) const {
if (getPrimaryContext() != this)
return getPrimaryContext()->Encloses(DC);
@@ -652,6 +599,9 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
ExternalASTSource *Source = getParentASTContext().getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
+ // Notify that we have a DeclContext that is initializing.
+ ExternalASTSource::Deserializing ADeclContext(Source);
+
llvm::SmallVector<Decl*, 64> Decls;
if (Source->FindExternalLexicalDecls(this, Decls))
return;
@@ -701,19 +651,6 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclContext::lookup_result
ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
- const VisibleDeclaration &VD) {
- ASTContext &Context = DC->getParentASTContext();
- StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr))
- Map = DC->CreateStoredDeclsMap(Context);
-
- StoredDeclsList &List = (*Map)[VD.Name];
- List.setFromDeclIDs(VD.Declarations);
- return List.getLookupResult(Context);
-}
-
-DeclContext::lookup_result
-ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls) {
ASTContext &Context = DC->getParentASTContext();;
@@ -730,35 +667,34 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
List.AddSubsequentDecl(Decls[I]);
}
- return List.getLookupResult(Context);
+ return List.getLookupResult();
}
-void ExternalASTSource::SetExternalVisibleDecls(const DeclContext *DC,
- const llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
- // There is no longer any visible storage in this context.
- DC->ExternalVisibleStorage = false;
-
- assert(!DC->LookupPtr && "Have a lookup map before de-serialization?");
- StoredDeclsMap *Map = DC->CreateStoredDeclsMap(DC->getParentASTContext());
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations);
+void ExternalASTSource::MaterializeVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls) {
+ assert(DC->LookupPtr);
+ StoredDeclsMap &Map = *DC->LookupPtr;
+
+ // If there's an entry in the table the visible decls for this name have
+ // already been deserialized.
+ if (Map.find(Name) == Map.end()) {
+ StoredDeclsList &List = Map[Name];
+ for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ if (List.isNull())
+ List.setOnlyValue(Decls[I]);
+ else
+ List.AddSubsequentDecl(Decls[I]);
+ }
}
}
-void ExternalASTSource::SetExternalVisibleDecls(const DeclContext *DC,
- const llvm::SmallVectorImpl<NamedDecl*> &Decls) {
- // There is no longer any visible storage in this context.
- DC->ExternalVisibleStorage = false;
+DeclContext::decl_iterator DeclContext::noload_decls_begin() const {
+ return decl_iterator(FirstDecl);
+}
- assert(!DC->LookupPtr && "Have a lookup map before de-serialization?");
- StoredDeclsMap &Map = *DC->CreateStoredDeclsMap(DC->getParentASTContext());
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- StoredDeclsList &List = Map[Decls[I]->getDeclName()];
- if (List.isNull())
- List.setOnlyValue(Decls[I]);
- else
- List.AddSubsequentDecl(Decls[I]);
- }
+DeclContext::decl_iterator DeclContext::noload_decls_end() const {
+ return decl_iterator();
}
DeclContext::decl_iterator DeclContext::decls_begin() const {
@@ -866,10 +802,10 @@ void DeclContext::buildLookup(DeclContext *DCtx) {
I != IEnd; ++I)
makeDeclVisibleInContextImpl(I->getInterface());
- // If this declaration is itself a transparent declaration context,
- // add its members (recursively).
+ // If this declaration is itself a transparent declaration context or
+ // inline namespace, add its members (recursively).
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
- if (InnerCtx->isTransparentContext())
+ if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
buildLookup(InnerCtx->getPrimaryContext());
}
}
@@ -886,7 +822,7 @@ DeclContext::lookup(DeclarationName Name) {
if (LookupPtr) {
StoredDeclsMap::iterator I = LookupPtr->find(Name);
if (I != LookupPtr->end())
- return I->second.getLookupResult(getParentASTContext());
+ return I->second.getLookupResult();
}
ExternalASTSource *Source = getParentASTContext().getExternalSource();
@@ -906,7 +842,7 @@ DeclContext::lookup(DeclarationName Name) {
StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
if (Pos == LookupPtr->end())
return lookup_result(lookup_iterator(0), lookup_iterator(0));
- return Pos->second.getLookupResult(getParentASTContext());
+ return Pos->second.getLookupResult();
}
DeclContext::lookup_const_result
@@ -914,7 +850,7 @@ DeclContext::lookup(DeclarationName Name) const {
return const_cast<DeclContext*>(this)->lookup(Name);
}
-DeclContext *DeclContext::getLookupContext() {
+DeclContext *DeclContext::getRedeclContext() {
DeclContext *Ctx = this;
// Skip through transparent contexts.
while (Ctx->isTransparentContext())
@@ -925,11 +861,29 @@ DeclContext *DeclContext::getLookupContext() {
DeclContext *DeclContext::getEnclosingNamespaceContext() {
DeclContext *Ctx = this;
// Skip through non-namespace, non-translation-unit contexts.
- while (!Ctx->isFileContext() || Ctx->isTransparentContext())
+ while (!Ctx->isFileContext())
Ctx = Ctx->getParent();
return Ctx->getPrimaryContext();
}
+bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
+ // For non-file contexts, this is equivalent to Equals.
+ if (!isFileContext())
+ return O->Equals(this);
+
+ do {
+ if (O->Equals(this))
+ return true;
+
+ const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(O);
+ if (!NS || !NS->isInline())
+ break;
+ O = NS->getParent();
+ } while (O);
+
+ return false;
+}
+
void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
// FIXME: This feels like a hack. Should DeclarationName support
// template-ids, or is there a better way to keep specializations
@@ -953,9 +907,9 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
if (LookupPtr || !Recoverable || hasExternalVisibleStorage())
makeDeclVisibleInContextImpl(D);
- // If we are a transparent context, insert into our parent context,
- // too. This operation is recursive.
- if (isTransparentContext())
+ // If we are a transparent context or inline namespace, insert into our
+ // parent context, too. This operation is recursive.
+ if (isTransparentContext() || isInlineNamespace())
getParent()->makeDeclVisibleInContext(D, Recoverable);
}
@@ -970,18 +924,21 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
if (isa<ClassTemplateSpecializationDecl>(D))
return;
- // If there is an external AST source, load any declarations it knows about
- // with this declaration's name.
- if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
- if (hasExternalVisibleStorage())
- Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
-
ASTContext *C = 0;
if (!LookupPtr) {
C = &getParentASTContext();
CreateStoredDeclsMap(*C);
}
+ // If there is an external AST source, load any declarations it knows about
+ // with this declaration's name.
+ // If the lookup table contains an entry about this name it means that we
+ // have already checked the external source.
+ if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
+ if (hasExternalVisibleStorage() &&
+ LookupPtr->find(D->getDeclName()) == LookupPtr->end())
+ Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
+
// Insert this declaration into the map.
StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
if (DeclNameEntries.isNull()) {
@@ -992,16 +949,22 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
// If it is possible that this is a redeclaration, check to see if there is
// already a decl for which declarationReplaces returns true. If there is
// one, just replace it and return.
- if (!C)
- C = &getParentASTContext();
-
- if (DeclNameEntries.HandleRedeclaration(*C, D))
+ if (DeclNameEntries.HandleRedeclaration(D))
return;
// Put this declaration into the appropriate slot.
DeclNameEntries.AddSubsequentDecl(D);
}
+void DeclContext::MaterializeVisibleDeclsFromExternalStorage() {
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ assert(hasExternalVisibleStorage() && Source && "No external storage?");
+
+ if (!LookupPtr)
+ CreateStoredDeclsMap(getParentASTContext());
+ Source->MaterializeVisibleDecls(this);
+}
+
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
/// this context.
DeclContext::udir_iterator_range
@@ -1011,43 +974,6 @@ DeclContext::getUsingDirectives() const {
reinterpret_cast<udir_iterator>(Result.second));
}
-void StoredDeclsList::materializeDecls(ASTContext &Context) {
- if (isNull())
- return;
-
- switch ((DataKind)(Data & 0x03)) {
- case DK_Decl:
- case DK_Decl_Vector:
- break;
-
- case DK_DeclID: {
- // Resolve this declaration ID to an actual declaration by
- // querying the external AST source.
- unsigned DeclID = Data >> 2;
-
- ExternalASTSource *Source = Context.getExternalSource();
- assert(Source && "No external AST source available!");
-
- Data = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(DeclID));
- break;
- }
-
- case DK_ID_Vector: {
- // We have a vector of declaration IDs. Resolve all of them to
- // actual declarations.
- VectorTy &Vector = *getAsVector();
- ExternalASTSource *Source = Context.getExternalSource();
- assert(Source && "No external AST source available!");
-
- for (unsigned I = 0, N = Vector.size(); I != N; ++I)
- Vector[I] = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(Vector[I]));
-
- Data = (Data & ~0x03) | DK_Decl_Vector;
- break;
- }
- }
-}
-
//===----------------------------------------------------------------------===//
// Creation and Destruction of StoredDeclsMaps. //
//===----------------------------------------------------------------------===//
@@ -1073,7 +999,6 @@ void ASTContext::ReleaseDeclContextMaps() {
// It's okay to delete DependentStoredDeclsMaps via a StoredDeclsMap
// pointer because the subclass doesn't add anything that needs to
// be deleted.
-
StoredDeclsMap::DestroyAll(LastSDM.getPointer(), LastSDM.getInt());
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index dd0fe08979f0..f2f0694826c6 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -65,18 +65,6 @@ CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, EmptyShell Empty) {
SourceLocation());
}
-CXXRecordDecl::~CXXRecordDecl() {
-}
-
-void CXXRecordDecl::Destroy(ASTContext &C) {
- if (data().Definition == this) {
- C.Deallocate(data().Bases);
- C.Deallocate(data().VBases);
- C.Deallocate(&data());
- }
- this->RecordDecl::Destroy(C);
-}
-
void
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
unsigned NumBases) {
@@ -133,19 +121,19 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
data().NumVBases = VBases.size();
for (int I = 0, E = VBases.size(); I != E; ++I) {
- QualType VBaseType = VBases[I]->getType();
-
+ TypeSourceInfo *VBaseTypeInfo = VBases[I]->getTypeSourceInfo();
+
// Skip dependent types; we can't do any checking on them now.
- if (VBaseType->isDependentType())
+ if (VBaseTypeInfo->getType()->isDependentType())
continue;
- CXXRecordDecl *VBaseClassDecl
- = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
+ CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>(
+ VBaseTypeInfo->getType()->getAs<RecordType>()->getDecl());
data().VBases[I] =
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
VBaseClassDecl->getTagKind() == TTK_Class,
- VBases[I]->getAccessSpecifier(), VBaseType);
+ VBases[I]->getAccessSpecifier(), VBaseTypeInfo);
}
}
@@ -621,7 +609,8 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
DeclContext::lookup_const_iterator I, E;
llvm::tie(I, E) = lookup(Name);
- assert(I != E && "Did not find a destructor!");
+ if (I == E)
+ return 0;
CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I);
assert(++I == E && "Found more than one destructor!");
@@ -631,10 +620,10 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
CXXMethodDecl *
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isStatic, StorageClass SCAsWritten, bool isInline) {
- return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, TInfo,
+ return new (C) CXXMethodDecl(CXXMethod, RD, NameInfo, T, TInfo,
isStatic, SCAsWritten, isInline);
}
@@ -796,13 +785,6 @@ CXXBaseOrMemberInitializer::Create(ASTContext &Context,
L, Init, R, Indices, NumIndices);
}
-void CXXBaseOrMemberInitializer::Destroy(ASTContext &Context) {
- if (Init)
- Init->Destroy(Context);
- // FIXME: Destroy indices
- this->~CXXBaseOrMemberInitializer();
-}
-
TypeLoc CXXBaseOrMemberInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return BaseOrMember.get<TypeSourceInfo*>()->getTypeLoc();
@@ -837,20 +819,21 @@ SourceRange CXXBaseOrMemberInitializer::getSourceRange() const {
CXXConstructorDecl *
CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationName(),
+ return new (C) CXXConstructorDecl(0, DeclarationNameInfo(),
QualType(), 0, false, false, false);
}
CXXConstructorDecl *
CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit,
bool isInline,
bool isImplicitlyDeclared) {
- assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
+ assert(NameInfo.getName().getNameKind()
+ == DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
- return new (C) CXXConstructorDecl(RD, L, N, T, TInfo, isExplicit,
+ return new (C) CXXConstructorDecl(RD, NameInfo, T, TInfo, isExplicit,
isInline, isImplicitlyDeclared);
}
@@ -945,40 +928,38 @@ bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const {
CXXDestructorDecl *
CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXDestructorDecl(0, SourceLocation(), DeclarationName(),
+ return new (C) CXXDestructorDecl(0, DeclarationNameInfo(),
QualType(), false, false);
}
CXXDestructorDecl *
CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, bool isInline,
bool isImplicitlyDeclared) {
- assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
+ assert(NameInfo.getName().getNameKind()
+ == DeclarationName::CXXDestructorName &&
"Name must refer to a destructor");
- return new (C) CXXDestructorDecl(RD, L, N, T, isInline, isImplicitlyDeclared);
-}
-
-void
-CXXConstructorDecl::Destroy(ASTContext& C) {
- C.Deallocate(BaseOrMemberInitializers);
- CXXMethodDecl::Destroy(C);
+ return new (C) CXXDestructorDecl(RD, NameInfo, T, isInline,
+ isImplicitlyDeclared);
}
CXXConversionDecl *
CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationName(),
+ return new (C) CXXConversionDecl(0, DeclarationNameInfo(),
QualType(), 0, false, false);
}
CXXConversionDecl *
CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicit) {
- assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+ assert(NameInfo.getName().getNameKind()
+ == DeclarationName::CXXConversionFunctionName &&
"Name must refer to a conversion function");
- return new (C) CXXConversionDecl(RD, L, N, T, TInfo, isInline, isExplicit);
+ return new (C) CXXConversionDecl(RD, NameInfo, T, TInfo,
+ isInline, isExplicit);
}
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
@@ -1009,14 +990,8 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
return cast_or_null<NamespaceDecl>(NominatedNamespace);
}
-void UsingDirectiveDecl::setNominatedNamespace(NamedDecl* ND) {
- assert((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
- "expected a NamespaceDecl or NamespaceAliasDecl");
- NominatedNamespace = ND;
-}
-
NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
+ SourceLocation UsingLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
SourceRange QualifierRange,
@@ -1025,15 +1000,16 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
NamedDecl *Namespace) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
- return new (C) NamespaceAliasDecl(DC, L, AliasLoc, Alias, QualifierRange,
+ return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, QualifierRange,
Qualifier, IdentLoc, Namespace);
}
UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, SourceRange NNR, SourceLocation UL,
- NestedNameSpecifier* TargetNNS, DeclarationName Name,
- bool IsTypeNameArg) {
- return new (C) UsingDecl(DC, L, NNR, UL, TargetNNS, Name, IsTypeNameArg);
+ SourceRange NNR, SourceLocation UL,
+ NestedNameSpecifier* TargetNNS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsTypeNameArg) {
+ return new (C) UsingDecl(DC, NNR, UL, TargetNNS, NameInfo, IsTypeNameArg);
}
UnresolvedUsingValueDecl *
@@ -1041,11 +1017,9 @@ UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceRange TargetNNR,
NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc,
- DeclarationName TargetName) {
+ const DeclarationNameInfo &NameInfo) {
return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
- TargetNNR, TargetNNS,
- TargetNameLoc, TargetName);
+ TargetNNR, TargetNNS, NameInfo);
}
UnresolvedUsingTypenameDecl *
@@ -1068,15 +1042,6 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) StaticAssertDecl(DC, L, AssertExpr, Message);
}
-void StaticAssertDecl::Destroy(ASTContext& C) {
- AssertExpr->Destroy(C);
- Message->Destroy(C);
- Decl::Destroy(C);
-}
-
-StaticAssertDecl::~StaticAssertDecl() {
-}
-
static const char *getAccessName(AccessSpecifier AS) {
switch (AS) {
default:
@@ -1096,5 +1061,3 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
AccessSpecifier AS) {
return DB << getAccessName(AS);
}
-
-
diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp
index 434bf00d354e..036acc2d77a5 100644
--- a/lib/AST/DeclGroup.cpp
+++ b/lib/AST/DeclGroup.cpp
@@ -30,9 +30,3 @@ DeclGroup::DeclGroup(unsigned numdecls, Decl** decls) : NumDecls(numdecls) {
assert(decls);
memcpy(this+1, decls, numdecls * sizeof(*decls));
}
-
-void DeclGroup::Destroy(ASTContext& C) {
- // Decls are destroyed by the DeclContext.
- this->~DeclGroup();
- C.Deallocate((void*) this);
-}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index adb0e7d08345..d952cc36ef1d 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -21,14 +21,8 @@ using namespace clang;
// ObjCListBase
//===----------------------------------------------------------------------===//
-void ObjCListBase::Destroy(ASTContext &Ctx) {
- Ctx.Deallocate(List);
- NumElts = 0;
- List = 0;
-}
-
void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
- assert(List == 0 && "Elements already set!");
+ List = 0;
if (Elts == 0) return; // Setting to an empty list is a noop.
@@ -47,12 +41,6 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
set(InList, Elts, Ctx);
}
-void ObjCProtocolList::Destroy(ASTContext &Ctx) {
- Ctx.Deallocate(Locations);
- Locations = 0;
- ObjCList<ObjCProtocolDecl>::Destroy(Ctx);
-}
-
//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
@@ -132,8 +120,9 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
return P;
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator
- I = OID->protocol_begin(), E = OID->protocol_end(); I != E; ++I)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = OID->all_referenced_protocol_begin(),
+ E = OID->all_referenced_protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
@@ -169,8 +158,9 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
return PD;
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator
- I = protocol_begin(), E = protocol_end(); I != E; ++I)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = all_referenced_protocol_begin(),
+ E = all_referenced_protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
@@ -179,23 +169,23 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
- const SourceLocation *Locs,
ASTContext &C)
{
- if (ReferencedProtocols.empty()) {
- ReferencedProtocols.set(ExtList, ExtNum, Locs, C);
+ if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
+ AllReferencedProtocols.set(ExtList, ExtNum, C);
return;
}
+
// Check for duplicate protocol in class's protocol list.
- // This is (O)2. But it is extremely rare and number of protocols in
+ // This is O(n*m). But it is extremely rare and number of protocols in
// class or its extension are very few.
llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
for (unsigned i = 0; i < ExtNum; i++) {
bool protocolExists = false;
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
- for (protocol_iterator p = protocol_begin(), e = protocol_end();
- p != e; p++) {
+ for (all_protocol_iterator
+ p = all_referenced_protocol_begin(),
+ e = all_referenced_protocol_end(); p != e; ++p) {
ObjCProtocolDecl *Proto = (*p);
if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
protocolExists = true;
@@ -204,23 +194,20 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
}
// Do we want to warn on a protocol in extension class which
// already exist in the class? Probably not.
- if (!protocolExists) {
+ if (!protocolExists)
ProtocolRefs.push_back(ProtoInExtension);
- ProtocolLocs.push_back(Locs[i]);
- }
}
+
if (ProtocolRefs.empty())
return;
+
// Merge ProtocolRefs into class's protocol list;
- protocol_loc_iterator pl = protocol_loc_begin();
- for (protocol_iterator p = protocol_begin(), e = protocol_end();
- p != e; ++p, ++pl) {
+ for (all_protocol_iterator p = all_referenced_protocol_begin(),
+ e = all_referenced_protocol_end(); p != e; ++p) {
ProtocolRefs.push_back(*p);
- ProtocolLocs.push_back(*pl);
}
- ReferencedProtocols.Destroy(C);
- unsigned NumProtoRefs = ProtocolRefs.size();
- setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
+
+ AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
}
/// getFirstClassExtension - Find first class extension of the given class.
@@ -339,27 +326,17 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
bool isInstance,
bool isVariadic,
bool isSynthesized,
+ bool isDefined,
ImplementationControl impControl,
unsigned numSelectorArgs) {
return new (C) ObjCMethodDecl(beginLoc, endLoc,
SelInfo, T, ResultTInfo, contextDecl,
isInstance,
- isVariadic, isSynthesized, impControl,
+ isVariadic, isSynthesized, isDefined,
+ impControl,
numSelectorArgs);
}
-void ObjCMethodDecl::Destroy(ASTContext &C) {
- if (Body) Body->Destroy(C);
- if (SelfDecl) SelfDecl->Destroy(C);
-
- for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
- if (*I) (*I)->Destroy(C);
-
- ParamInfo.Destroy(C);
-
- Decl::Destroy(C);
-}
-
/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
@@ -465,22 +442,11 @@ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal)
: ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
TypeForDecl(0), SuperClass(0),
- CategoryList(0), ForwardDecl(FD), InternalInterface(isInternal),
+ CategoryList(0), IvarList(0),
+ ForwardDecl(FD), InternalInterface(isInternal),
ClassLoc(CLoc) {
}
-void ObjCInterfaceDecl::Destroy(ASTContext &C) {
- for (ivar_iterator I = ivar_begin(), E = ivar_end(); I != E; ++I)
- if (*I) (*I)->Destroy(C);
-
- // FIXME: CategoryList?
-
- // FIXME: Because there is no clear ownership
- // role between ObjCInterfaceDecls and the ObjCPropertyDecls that they
- // reference, we destroy ObjCPropertyDecls in ~TranslationUnit.
- Decl::Destroy(C);
-}
-
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
return getASTContext().getObjCImplementation(
const_cast<ObjCInterfaceDecl*>(this));
@@ -490,6 +456,49 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
getASTContext().setObjCImplementation(this, ImplD);
}
+/// all_declared_ivar_begin - return first ivar declared in this class,
+/// its extensions and its implementation. Lazily build the list on first
+/// access.
+ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
+ if (IvarList)
+ return IvarList;
+
+ ObjCIvarDecl *curIvar = 0;
+ if (!ivar_empty()) {
+ ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
+ IvarList = (*I); ++I;
+ for (curIvar = IvarList; I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+
+ for (const ObjCCategoryDecl *CDecl = getFirstClassExtension(); CDecl;
+ CDecl = CDecl->getNextClassExtension()) {
+ if (!CDecl->ivar_empty()) {
+ ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
+ E = CDecl->ivar_end();
+ if (!IvarList) {
+ IvarList = (*I); ++I;
+ curIvar = IvarList;
+ }
+ for ( ;I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+ }
+
+ if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
+ if (!ImplDecl->ivar_empty()) {
+ ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
+ E = ImplDecl->ivar_end();
+ if (!IvarList) {
+ IvarList = (*I); ++I;
+ curIvar = IvarList;
+ }
+ for ( ;I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+ }
+ return IvarList;
+}
/// FindCategoryDeclaration - Finds category declaration in the list of
/// categories for this class and returns it. Name of the category is passed
@@ -575,7 +584,8 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
- AccessControl ac, Expr *BW) {
+ AccessControl ac, Expr *BW,
+ bool synthesized) {
if (DC) {
// Ivar's can only appear in interfaces, implementations (via synthesized
// properties), and class extensions (via direct declaration, or synthesized
@@ -590,9 +600,26 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
isa<ObjCCategoryDecl>(DC)) &&
"Invalid ivar decl context!");
+ // Once a new ivar is created in any of class/class-extension/implementation
+ // decl contexts, the previously built IvarList must be rebuilt.
+ ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
+ if (!ID) {
+ if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC)) {
+ ID = IM->getClassInterface();
+ if (BW)
+ IM->setHasSynthBitfield(true);
+ }
+ else {
+ ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
+ ID = CD->getClassInterface();
+ if (BW)
+ CD->setHasSynthBitfield(true);
+ }
+ }
+ ID->setIvarList(0);
}
- return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW);
+ return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW, synthesized);
}
const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
@@ -630,11 +657,6 @@ ObjCAtDefsFieldDecl
return new (C) ObjCAtDefsFieldDecl(DC, L, Id, T, BW);
}
-void ObjCAtDefsFieldDecl::Destroy(ASTContext& C) {
- this->~ObjCAtDefsFieldDecl();
- C.Deallocate((void *)this);
-}
-
//===----------------------------------------------------------------------===//
// ObjCProtocolDecl
//===----------------------------------------------------------------------===//
@@ -645,11 +667,6 @@ ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ObjCProtocolDecl(DC, L, Id);
}
-void ObjCProtocolDecl::Destroy(ASTContext &C) {
- ReferencedProtocols.Destroy(C);
- ObjCContainerDecl::Destroy(C);
-}
-
ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
ObjCProtocolDecl *PDecl = this;
@@ -709,23 +726,6 @@ ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C);
}
-void ObjCClassDecl::Destroy(ASTContext &C) {
- // ObjCInterfaceDecls registered with a DeclContext will get destroyed
- // when the DeclContext is destroyed. For those created only by a forward
- // declaration, the first @class that created the ObjCInterfaceDecl gets
- // to destroy it.
- // FIXME: Note that this ownership role is very brittle; a better
- // polict is surely need in the future.
- for (iterator I = begin(), E = end(); I !=E ; ++I) {
- ObjCInterfaceDecl *ID = I->getInterface();
- if (ID->isForwardDecl() && ID->getLocStart() == getLocStart())
- ID->Destroy(C);
- }
-
- C.Deallocate(ForwardDecls);
- Decl::Destroy(C);
-}
-
SourceRange ObjCClassDecl::getSourceRange() const {
// FIXME: We should include the semicolon
assert(NumDecls);
@@ -754,11 +754,6 @@ ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, Locs, C);
}
-void ObjCForwardProtocolDecl::Destroy(ASTContext &C) {
- ReferencedProtocols.Destroy(C);
- Decl::Destroy(C);
-}
-
//===----------------------------------------------------------------------===//
// ObjCCategoryDecl
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 765772dd13f9..f18d2f0215dd 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -198,6 +198,12 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
llvm::SmallVector<Decl*, 2> Decls;
for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
D != DEnd; ++D) {
+
+ // Don't print ObjCIvarDecls, as they are printed when visiting the
+ // containing ObjCInterfaceDecl.
+ if (isa<ObjCIvarDecl>(*D))
+ continue;
+
if (!Policy.Dump) {
// Skip over implicit declarations in pretty-printing mode.
if (D->isImplicit()) continue;
@@ -329,10 +335,11 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!Policy.SuppressSpecifiers) {
switch (D->getStorageClass()) {
- case FunctionDecl::None: break;
- case FunctionDecl::Extern: Out << "extern "; break;
- case FunctionDecl::Static: Out << "static "; break;
- case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
+ case SC_None: break;
+ case SC_Extern: Out << "extern "; break;
+ case SC_Static: Out << "static "; break;
+ case SC_PrivateExtern: Out << "__private_extern__ "; break;
+ case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions");
}
if (D->isInlineSpecified()) Out << "inline ";
@@ -341,7 +348,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressSpecifiers = false;
- std::string Proto = D->getNameAsString();
+ std::string Proto = D->getNameInfo().getAsString();
if (isa<FunctionType>(D->getType().getTypePtr())) {
const FunctionType *AFT = D->getType()->getAs<FunctionType>();
@@ -499,7 +506,7 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
}
void DeclPrinter::VisitVarDecl(VarDecl *D) {
- if (!Policy.SuppressSpecifiers && D->getStorageClass() != VarDecl::None)
+ if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None)
Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " ";
if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 9e1d79d79d6b..e69338a7730d 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -84,10 +84,59 @@ unsigned TemplateParameterList::getDepth() const {
}
//===----------------------------------------------------------------------===//
-// TemplateDecl Implementation
+// RedeclarableTemplateDecl Implementation
//===----------------------------------------------------------------------===//
-TemplateDecl::~TemplateDecl() {
+RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
+ // Find the first declaration of this function template.
+ RedeclarableTemplateDecl *First = getCanonicalDecl();
+
+ if (First->CommonOrPrev.isNull()) {
+ CommonBase *CommonPtr = First->newCommon();
+ First->CommonOrPrev = CommonPtr;
+ CommonPtr->Latest = First;
+ }
+ return First->CommonOrPrev.get<CommonBase*>();
+}
+
+
+RedeclarableTemplateDecl *RedeclarableTemplateDecl::getCanonicalDeclImpl() {
+ RedeclarableTemplateDecl *Tmpl = this;
+ while (Tmpl->getPreviousDeclaration())
+ Tmpl = Tmpl->getPreviousDeclaration();
+ return Tmpl;
+}
+
+void RedeclarableTemplateDecl::setPreviousDeclarationImpl(
+ RedeclarableTemplateDecl *Prev) {
+ if (Prev) {
+ CommonBase *Common = Prev->getCommonPtr();
+ Prev = Common->Latest;
+ Common->Latest = this;
+ CommonOrPrev = Prev;
+ } else {
+ assert(CommonOrPrev.is<CommonBase*>() && "Cannot reset TemplateDecl Prev");
+ }
+}
+
+RedeclarableTemplateDecl *RedeclarableTemplateDecl::getNextRedeclaration() {
+ if (CommonOrPrev.is<RedeclarableTemplateDecl*>())
+ return CommonOrPrev.get<RedeclarableTemplateDecl*>();
+ CommonBase *Common = CommonOrPrev.get<CommonBase*>();
+ return Common ? Common->Latest : this;
+}
+
+template <class EntryType>
+typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType*
+RedeclarableTemplateDecl::findSpecializationImpl(
+ llvm::FoldingSet<EntryType> &Specs,
+ const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos) {
+ typedef SpecEntryTraits<EntryType> SETraits;
+ llvm::FoldingSetNodeID ID;
+ EntryType::Profile(ID,Args,NumArgs, getASTContext());
+ EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
+ return Entry ? SETraits::getMostRecentDeclaration(Entry) : 0;
}
//===----------------------------------------------------------------------===//
@@ -107,37 +156,16 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
}
-void FunctionTemplateDecl::Destroy(ASTContext &C) {
- if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) {
- for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
- Spec = CommonPtr->Specializations.begin(),
- SpecEnd = CommonPtr->Specializations.end();
- Spec != SpecEnd; ++Spec)
- C.Deallocate(&*Spec);
- }
-
- Decl::Destroy(C);
+RedeclarableTemplateDecl::CommonBase *FunctionTemplateDecl::newCommon() {
+ Common *CommonPtr = new (getASTContext()) Common;
+ getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
+ return CommonPtr;
}
-FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() {
- FunctionTemplateDecl *FunTmpl = this;
- while (FunTmpl->getPreviousDeclaration())
- FunTmpl = FunTmpl->getPreviousDeclaration();
- return FunTmpl;
-}
-
-FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() {
- // Find the first declaration of this function template.
- FunctionTemplateDecl *First = this;
- while (First->getPreviousDeclaration())
- First = First->getPreviousDeclaration();
-
- if (First->CommonOrPrev.isNull()) {
- Common *CommonPtr = new (getASTContext()) Common;
- getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
- First->CommonOrPrev = CommonPtr;
- }
- return First->CommonOrPrev.get<Common*>();
+FunctionDecl *
+FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos) {
+ return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
}
//===----------------------------------------------------------------------===//
@@ -148,13 +176,6 @@ void ClassTemplateDecl::DeallocateCommon(void *Ptr) {
static_cast<Common *>(Ptr)->~Common();
}
-ClassTemplateDecl *ClassTemplateDecl::getCanonicalDecl() {
- ClassTemplateDecl *Template = this;
- while (Template->getPreviousDeclaration())
- Template = Template->getPreviousDeclaration();
- return Template;
-}
-
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
DeclContext *DC,
SourceLocation L,
@@ -167,8 +188,24 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
return New;
}
-void ClassTemplateDecl::Destroy(ASTContext& C) {
- Decl::Destroy(C);
+RedeclarableTemplateDecl::CommonBase *ClassTemplateDecl::newCommon() {
+ Common *CommonPtr = new (getASTContext()) Common;
+ getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
+ return CommonPtr;
+}
+
+ClassTemplateSpecializationDecl *
+ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos) {
+ return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
+}
+
+ClassTemplatePartialSpecializationDecl *
+ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs,
+ void *&InsertPos) {
+ return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs,
+ InsertPos);
}
void ClassTemplateDecl::getPartialSpecializations(
@@ -181,7 +218,7 @@ void ClassTemplateDecl::getPartialSpecializations(
P = PartialSpecs.begin(), PEnd = PartialSpecs.end();
P != PEnd; ++P) {
assert(!PS[P->getSequenceNumber()]);
- PS[P->getSequenceNumber()] = &*P;
+ PS[P->getSequenceNumber()] = P->getMostRecentDeclaration();
}
}
@@ -194,7 +231,22 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) {
PEnd = getPartialSpecializations().end();
P != PEnd; ++P) {
if (Context.hasSameType(P->getInjectedSpecializationType(), T))
- return &*P;
+ return P->getMostRecentDeclaration();
+ }
+
+ return 0;
+}
+
+ClassTemplatePartialSpecializationDecl *
+ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *D) {
+ Decl *DCanon = D->getCanonicalDecl();
+ for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+ P = getPartialSpecializations().begin(),
+ PEnd = getPartialSpecializations().end();
+ P != PEnd; ++P) {
+ if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
+ return P->getMostRecentDeclaration();
}
return 0;
@@ -239,20 +291,6 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
return CommonPtr->InjectedClassNameType;
}
-ClassTemplateDecl::Common *ClassTemplateDecl::getCommonPtr() {
- // Find the first declaration of this function template.
- ClassTemplateDecl *First = this;
- while (First->getPreviousDeclaration())
- First = First->getPreviousDeclaration();
-
- if (First->CommonOrPrev.isNull()) {
- Common *CommonPtr = new (getASTContext()) Common;
- getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
- First->CommonOrPrev = CommonPtr;
- }
- return First->CommonOrPrev.get<Common*>();
-}
-
//===----------------------------------------------------------------------===//
// TemplateTypeParm Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
@@ -431,15 +469,6 @@ StructuredArguments.setPointer(NewArgs);
StructuredArguments.setInt(0); // Doesn't own the pointer.
}
-void TemplateArgumentList::Destroy(ASTContext &C) {
- if (FlatArguments.getInt())
- C.Deallocate((void*)FlatArguments.getPointer());
- if (StructuredArguments.getInt())
- C.Deallocate((void*)StructuredArguments.getPointer());
-}
-
-TemplateArgumentList::~TemplateArgumentList() {}
-
//===----------------------------------------------------------------------===//
// ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
@@ -487,16 +516,6 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, EmptyShell Empty) {
new (Context)ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
}
-void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
- delete ExplicitInfo;
-
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
- C.Deallocate(PartialSpec);
-
- CXXRecordDecl::Destroy(C);
-}
-
void
ClassTemplateSpecializationDecl::getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
@@ -584,3 +603,8 @@ FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
= new (Context) FriendTemplateDecl(DC, L, NParams, Params, Friend, FLoc);
return Result;
}
+
+FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
+ EmptyShell Empty) {
+ return new (Context) FriendTemplateDecl(Empty);
+}
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 343d403e76ad..860a0b276a79 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/DenseMap.h"
@@ -404,26 +405,6 @@ DeclarationNameTable::~DeclarationNameTable() {
= static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
(CXXLiteralOperatorNames);
- if (Ctx.FreeMemory) {
- llvm::FoldingSetIterator<CXXSpecialName>
- SI = SpecialNames->begin(), SE = SpecialNames->end();
-
- while (SI != SE) {
- CXXSpecialName *n = &*SI++;
- Ctx.Deallocate(n);
- }
-
- llvm::FoldingSetIterator<CXXLiteralOperatorIdName>
- LI = LiteralNames->begin(), LE = LiteralNames->end();
-
- while (LI != LE) {
- CXXLiteralOperatorIdName *n = &*LI++;
- Ctx.Deallocate(n);
- }
-
- Ctx.Deallocate(CXXOperatorNames);
- }
-
delete SpecialNames;
delete LiteralNames;
}
@@ -505,3 +486,98 @@ getHashValue(clang::DeclarationName N) {
return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
}
+DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ NamedType.TInfo = 0;
+ break;
+ case DeclarationName::CXXOperatorName:
+ CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
+ CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ // FIXME: ?
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+}
+
+std::string DeclarationNameInfo::getAsString() const {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ printName(OS);
+ return OS.str();
+}
+
+void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXUsingDirective:
+ Name.printName(OS);
+ return;
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
+ if (Name.getNameKind() == DeclarationName::CXXDestructorName)
+ OS << '~';
+ else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
+ OS << "operator ";
+ OS << TInfo->getType().getAsString();
+ }
+ else
+ Name.printName(OS);
+ return;
+ }
+ assert(false && "Unexpected declaration name kind");
+}
+
+SourceLocation DeclarationNameInfo::getEndLoc() const {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ return NameLoc;
+
+ case DeclarationName::CXXOperatorName: {
+ unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
+ return SourceLocation::getFromRawEncoding(raw);
+ }
+
+ case DeclarationName::CXXLiteralOperatorName: {
+ unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
+ return SourceLocation::getFromRawEncoding(raw);
+ }
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
+ return TInfo->getTypeLoc().getEndLoc();
+ else
+ return NameLoc;
+
+ // DNInfo work in progress: FIXME.
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ return NameLoc;
+ }
+ assert(false && "Unexpected declaration name kind");
+ return SourceLocation();
+}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 6524a312dc8b..5feef1c80332 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -44,8 +44,8 @@ bool Expr::isKnownToHaveBooleanValue() const {
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(this)) {
switch (UO->getOpcode()) {
- case UnaryOperator::Plus:
- case UnaryOperator::Extension:
+ case UO_Plus:
+ case UO_Extension:
return UO->getSubExpr()->isKnownToHaveBooleanValue();
default:
return false;
@@ -60,25 +60,25 @@ bool Expr::isKnownToHaveBooleanValue() const {
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(this)) {
switch (BO->getOpcode()) {
default: return false;
- case BinaryOperator::LT: // Relational operators.
- case BinaryOperator::GT:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
- case BinaryOperator::EQ: // Equality operators.
- case BinaryOperator::NE:
- case BinaryOperator::LAnd: // AND operator.
- case BinaryOperator::LOr: // Logical OR operator.
+ case BO_LT: // Relational operators.
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ: // Equality operators.
+ case BO_NE:
+ case BO_LAnd: // AND operator.
+ case BO_LOr: // Logical OR operator.
return true;
- case BinaryOperator::And: // Bitwise AND operator.
- case BinaryOperator::Xor: // Bitwise XOR operator.
- case BinaryOperator::Or: // Bitwise OR operator.
+ case BO_And: // Bitwise AND operator.
+ case BO_Xor: // Bitwise XOR operator.
+ case BO_Or: // Bitwise OR operator.
// Handle things like (x==2)|(y==12).
return BO->getLHS()->isKnownToHaveBooleanValue() &&
BO->getRHS()->isKnownToHaveBooleanValue();
- case BinaryOperator::Comma:
- case BinaryOperator::Assign:
+ case BO_Comma:
+ case BO_Assign:
return BO->getRHS()->isKnownToHaveBooleanValue();
}
}
@@ -151,7 +151,7 @@ void DeclRefExpr::computeDependence() {
ValueDependent = true;
}
// (TD) - a template-id that is dependent,
- else if (hasExplicitTemplateArgumentList() &&
+ else if (hasExplicitTemplateArgs() &&
TemplateSpecializationType::anyDependentTemplateArguments(
getTemplateArgs(),
getNumTemplateArgs())) {
@@ -204,7 +204,29 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
}
if (TemplateArgs)
- getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs);
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
+
+ computeDependence();
+}
+
+DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ QualType T)
+ : Expr(DeclRefExprClass, T, false, false),
+ DecoratedD(D,
+ (Qualifier? HasQualifierFlag : 0) |
+ (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)),
+ Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) {
+ if (Qualifier) {
+ NameQualifier *NQ = getNameQualifier();
+ NQ->NNS = Qualifier;
+ NQ->Range = QualifierRange;
+ }
+
+ if (TemplateArgs)
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
computeDependence();
}
@@ -216,6 +238,18 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
SourceLocation NameLoc,
QualType T,
const TemplateArgumentListInfo *TemplateArgs) {
+ return Create(Context, Qualifier, QualifierRange, D,
+ DeclarationNameInfo(D->getDeclName(), NameLoc),
+ T, TemplateArgs);
+}
+
+DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D,
+ const DeclarationNameInfo &NameInfo,
+ QualType T,
+ const TemplateArgumentListInfo *TemplateArgs) {
std::size_t Size = sizeof(DeclRefExpr);
if (Qualifier != 0)
Size += sizeof(NameQualifier);
@@ -224,7 +258,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>());
- return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc,
+ return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameInfo,
TemplateArgs, T);
}
@@ -242,12 +276,10 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier,
}
SourceRange DeclRefExpr::getSourceRange() const {
- // FIXME: Does not handle multi-token names well, e.g., operator[].
- SourceRange R(Loc);
-
+ SourceRange R = getNameInfo().getSourceRange();
if (hasQualifier())
R.setBegin(getQualifierRange().getBegin());
- if (hasExplicitTemplateArgumentList())
+ if (hasExplicitTemplateArgs())
R.setEnd(getRAngleLoc());
return R;
}
@@ -342,6 +374,44 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
return "";
}
+void APNumericStorage::setIntValue(ASTContext &C, const llvm::APInt &Val) {
+ if (hasAllocation())
+ C.Deallocate(pVal);
+
+ BitWidth = Val.getBitWidth();
+ unsigned NumWords = Val.getNumWords();
+ const uint64_t* Words = Val.getRawData();
+ if (NumWords > 1) {
+ pVal = new (C) uint64_t[NumWords];
+ std::copy(Words, Words + NumWords, pVal);
+ } else if (NumWords == 1)
+ VAL = Words[0];
+ else
+ VAL = 0;
+}
+
+IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l) {
+ return new (C) IntegerLiteral(C, V, type, l);
+}
+
+IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) IntegerLiteral(Empty);
+}
+
+FloatingLiteral *
+FloatingLiteral::Create(ASTContext &C, const llvm::APFloat &V,
+ bool isexact, QualType Type, SourceLocation L) {
+ return new (C) FloatingLiteral(C, V, isexact, Type, L);
+}
+
+FloatingLiteral *
+FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) FloatingLiteral(Empty);
+}
+
/// getValueAsApproximateDouble - This returns the value as an inaccurate
/// double. Note that this may cause loss of precision, but is useful for
/// debugging dumps, etc.
@@ -390,15 +460,7 @@ StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) {
return SL;
}
-void StringLiteral::DoDestroy(ASTContext &C) {
- C.Deallocate(const_cast<char*>(StrData));
- Expr::DoDestroy(C);
-}
-
void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
- if (StrData)
- C.Deallocate(const_cast<char*>(StrData));
-
char *AStrData = new (C, 1) char[Str.size()];
memcpy(AStrData, Str.data(), Str.size());
StrData = AStrData;
@@ -410,48 +472,47 @@ void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
const char *UnaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
default: assert(0 && "Unknown unary operator");
- case PostInc: return "++";
- case PostDec: return "--";
- case PreInc: return "++";
- case PreDec: return "--";
- case AddrOf: return "&";
- case Deref: return "*";
- case Plus: return "+";
- case Minus: return "-";
- case Not: return "~";
- case LNot: return "!";
- case Real: return "__real";
- case Imag: return "__imag";
- case Extension: return "__extension__";
- case OffsetOf: return "__builtin_offsetof";
+ case UO_PostInc: return "++";
+ case UO_PostDec: return "--";
+ case UO_PreInc: return "++";
+ case UO_PreDec: return "--";
+ case UO_AddrOf: return "&";
+ case UO_Deref: return "*";
+ case UO_Plus: return "+";
+ case UO_Minus: return "-";
+ case UO_Not: return "~";
+ case UO_LNot: return "!";
+ case UO_Real: return "__real";
+ case UO_Imag: return "__imag";
+ case UO_Extension: return "__extension__";
}
}
-UnaryOperator::Opcode
+UnaryOperatorKind
UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) {
switch (OO) {
default: assert(false && "No unary operator for overloaded function");
- case OO_PlusPlus: return Postfix ? PostInc : PreInc;
- case OO_MinusMinus: return Postfix ? PostDec : PreDec;
- case OO_Amp: return AddrOf;
- case OO_Star: return Deref;
- case OO_Plus: return Plus;
- case OO_Minus: return Minus;
- case OO_Tilde: return Not;
- case OO_Exclaim: return LNot;
+ case OO_PlusPlus: return Postfix ? UO_PostInc : UO_PreInc;
+ case OO_MinusMinus: return Postfix ? UO_PostDec : UO_PreDec;
+ case OO_Amp: return UO_AddrOf;
+ case OO_Star: return UO_Deref;
+ case OO_Plus: return UO_Plus;
+ case OO_Minus: return UO_Minus;
+ case OO_Tilde: return UO_Not;
+ case OO_Exclaim: return UO_LNot;
}
}
OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
switch (Opc) {
- case PostInc: case PreInc: return OO_PlusPlus;
- case PostDec: case PreDec: return OO_MinusMinus;
- case AddrOf: return OO_Amp;
- case Deref: return OO_Star;
- case Plus: return OO_Plus;
- case Minus: return OO_Minus;
- case Not: return OO_Tilde;
- case LNot: return OO_Exclaim;
+ case UO_PostInc: case UO_PreInc: return OO_PlusPlus;
+ case UO_PostDec: case UO_PreDec: return OO_MinusMinus;
+ case UO_AddrOf: return OO_Amp;
+ case UO_Deref: return OO_Star;
+ case UO_Plus: return OO_Plus;
+ case UO_Minus: return OO_Minus;
+ case UO_Not: return OO_Tilde;
+ case UO_LNot: return OO_Exclaim;
default: return OO_None;
}
}
@@ -496,13 +557,6 @@ CallExpr::CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty)
SubExprs = new (C) Stmt*[1];
}
-void CallExpr::DoDestroy(ASTContext& C) {
- DestroyChildren(C);
- if (SubExprs) C.Deallocate(SubExprs);
- this->~CallExpr();
- C.Deallocate(this);
-}
-
Decl *CallExpr::getCalleeDecl() {
Expr *CEE = getCallee()->IgnoreParenCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
@@ -526,8 +580,6 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) {
// If shrinking # arguments, just delete the extras and forgot them.
if (NumArgs < getNumArgs()) {
- for (unsigned i = NumArgs, e = getNumArgs(); i != e; ++i)
- getArg(i)->Destroy(C);
this->NumArgs = NumArgs;
return;
}
@@ -640,7 +692,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
SourceRange qualrange,
ValueDecl *memberdecl,
DeclAccessPair founddecl,
- SourceLocation l,
+ DeclarationNameInfo nameinfo,
const TemplateArgumentListInfo *targs,
QualType ty) {
std::size_t Size = sizeof(MemberExpr);
@@ -655,7 +707,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
Size += ExplicitTemplateArgumentList::sizeFor(*targs);
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
- MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, l, ty);
+ MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, ty);
if (hasQualOrFound) {
if (qual && qual->isDependent()) {
@@ -672,7 +724,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
if (targs) {
E->HasExplicitTemplateArgumentList = true;
- E->getExplicitTemplateArgumentList()->initializeFrom(*targs);
+ E->getExplicitTemplateArgs().initializeFrom(*targs);
}
return E;
@@ -680,72 +732,68 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
const char *CastExpr::getCastKindName() const {
switch (getCastKind()) {
- case CastExpr::CK_Unknown:
+ case CK_Unknown:
return "Unknown";
- case CastExpr::CK_BitCast:
+ case CK_BitCast:
return "BitCast";
- case CastExpr::CK_LValueBitCast:
+ case CK_LValueBitCast:
return "LValueBitCast";
- case CastExpr::CK_NoOp:
+ case CK_NoOp:
return "NoOp";
- case CastExpr::CK_BaseToDerived:
+ case CK_BaseToDerived:
return "BaseToDerived";
- case CastExpr::CK_DerivedToBase:
+ case CK_DerivedToBase:
return "DerivedToBase";
- case CastExpr::CK_UncheckedDerivedToBase:
+ case CK_UncheckedDerivedToBase:
return "UncheckedDerivedToBase";
- case CastExpr::CK_Dynamic:
+ case CK_Dynamic:
return "Dynamic";
- case CastExpr::CK_ToUnion:
+ case CK_ToUnion:
return "ToUnion";
- case CastExpr::CK_ArrayToPointerDecay:
+ case CK_ArrayToPointerDecay:
return "ArrayToPointerDecay";
- case CastExpr::CK_FunctionToPointerDecay:
+ case CK_FunctionToPointerDecay:
return "FunctionToPointerDecay";
- case CastExpr::CK_NullToMemberPointer:
+ case CK_NullToMemberPointer:
return "NullToMemberPointer";
- case CastExpr::CK_BaseToDerivedMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
return "BaseToDerivedMemberPointer";
- case CastExpr::CK_DerivedToBaseMemberPointer:
+ case CK_DerivedToBaseMemberPointer:
return "DerivedToBaseMemberPointer";
- case CastExpr::CK_UserDefinedConversion:
+ case CK_UserDefinedConversion:
return "UserDefinedConversion";
- case CastExpr::CK_ConstructorConversion:
+ case CK_ConstructorConversion:
return "ConstructorConversion";
- case CastExpr::CK_IntegralToPointer:
+ case CK_IntegralToPointer:
return "IntegralToPointer";
- case CastExpr::CK_PointerToIntegral:
+ case CK_PointerToIntegral:
return "PointerToIntegral";
- case CastExpr::CK_ToVoid:
+ case CK_ToVoid:
return "ToVoid";
- case CastExpr::CK_VectorSplat:
+ case CK_VectorSplat:
return "VectorSplat";
- case CastExpr::CK_IntegralCast:
+ case CK_IntegralCast:
return "IntegralCast";
- case CastExpr::CK_IntegralToFloating:
+ case CK_IntegralToFloating:
return "IntegralToFloating";
- case CastExpr::CK_FloatingToIntegral:
+ case CK_FloatingToIntegral:
return "FloatingToIntegral";
- case CastExpr::CK_FloatingCast:
+ case CK_FloatingCast:
return "FloatingCast";
- case CastExpr::CK_MemberPointerToBoolean:
+ case CK_MemberPointerToBoolean:
return "MemberPointerToBoolean";
- case CastExpr::CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToObjCPointerCast:
return "AnyPointerToObjCPointerCast";
- case CastExpr::CK_AnyPointerToBlockPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
return "AnyPointerToBlockPointerCast";
+ case CK_ObjCObjectLValueCast:
+ return "ObjCObjectLValueCast";
}
assert(0 && "Unhandled cast kind!");
return 0;
}
-void CastExpr::DoDestroy(ASTContext &C)
-{
- BasePath.Destroy();
- Expr::DoDestroy(C);
-}
-
Expr *CastExpr::getSubExprAsWritten() {
Expr *SubExpr = 0;
CastExpr *E = this;
@@ -758,9 +806,9 @@ Expr *CastExpr::getSubExprAsWritten() {
// Conversions by constructor and conversion functions have a
// subexpression describing the call; strip it off.
- if (E->getCastKind() == CastExpr::CK_ConstructorConversion)
+ if (E->getCastKind() == CK_ConstructorConversion)
SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
- else if (E->getCastKind() == CastExpr::CK_UserDefinedConversion)
+ else if (E->getCastKind() == CK_UserDefinedConversion)
SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
// If the subexpression we're left with is an implicit cast, look
@@ -770,82 +818,142 @@ Expr *CastExpr::getSubExprAsWritten() {
return SubExpr;
}
+CXXBaseSpecifier **CastExpr::path_buffer() {
+ switch (getStmtClass()) {
+#define ABSTRACT_STMT(x)
+#define CASTEXPR(Type, Base) \
+ case Stmt::Type##Class: \
+ return reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1);
+#define STMT(Type, Base)
+#include "clang/AST/StmtNodes.inc"
+ default:
+ llvm_unreachable("non-cast expressions not possible here");
+ return 0;
+ }
+}
+
+void CastExpr::setCastPath(const CXXCastPath &Path) {
+ assert(Path.size() == path_size());
+ memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*));
+}
+
+ImplicitCastExpr *ImplicitCastExpr::Create(ASTContext &C, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ExprValueKind VK) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ ImplicitCastExpr *E =
+ new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
+}
+
+
+CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L, SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ CStyleCastExpr *E =
+ new (Buffer) CStyleCastExpr(T, K, Op, PathSize, WrittenTy, L, R);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CStyleCastExpr *CStyleCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
+}
+
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
const char *BinaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
- case PtrMemD: return ".*";
- case PtrMemI: return "->*";
- case Mul: return "*";
- case Div: return "/";
- case Rem: return "%";
- case Add: return "+";
- case Sub: return "-";
- case Shl: return "<<";
- case Shr: return ">>";
- case LT: return "<";
- case GT: return ">";
- case LE: return "<=";
- case GE: return ">=";
- case EQ: return "==";
- case NE: return "!=";
- case And: return "&";
- case Xor: return "^";
- case Or: return "|";
- case LAnd: return "&&";
- case LOr: return "||";
- case Assign: return "=";
- case MulAssign: return "*=";
- case DivAssign: return "/=";
- case RemAssign: return "%=";
- case AddAssign: return "+=";
- case SubAssign: return "-=";
- case ShlAssign: return "<<=";
- case ShrAssign: return ">>=";
- case AndAssign: return "&=";
- case XorAssign: return "^=";
- case OrAssign: return "|=";
- case Comma: return ",";
+ case BO_PtrMemD: return ".*";
+ case BO_PtrMemI: return "->*";
+ case BO_Mul: return "*";
+ case BO_Div: return "/";
+ case BO_Rem: return "%";
+ case BO_Add: return "+";
+ case BO_Sub: return "-";
+ case BO_Shl: return "<<";
+ case BO_Shr: return ">>";
+ case BO_LT: return "<";
+ case BO_GT: return ">";
+ case BO_LE: return "<=";
+ case BO_GE: return ">=";
+ case BO_EQ: return "==";
+ case BO_NE: return "!=";
+ case BO_And: return "&";
+ case BO_Xor: return "^";
+ case BO_Or: return "|";
+ case BO_LAnd: return "&&";
+ case BO_LOr: return "||";
+ case BO_Assign: return "=";
+ case BO_MulAssign: return "*=";
+ case BO_DivAssign: return "/=";
+ case BO_RemAssign: return "%=";
+ case BO_AddAssign: return "+=";
+ case BO_SubAssign: return "-=";
+ case BO_ShlAssign: return "<<=";
+ case BO_ShrAssign: return ">>=";
+ case BO_AndAssign: return "&=";
+ case BO_XorAssign: return "^=";
+ case BO_OrAssign: return "|=";
+ case BO_Comma: return ",";
}
return "";
}
-BinaryOperator::Opcode
+BinaryOperatorKind
BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
switch (OO) {
default: assert(false && "Not an overloadable binary operator");
- case OO_Plus: return Add;
- case OO_Minus: return Sub;
- case OO_Star: return Mul;
- case OO_Slash: return Div;
- case OO_Percent: return Rem;
- case OO_Caret: return Xor;
- case OO_Amp: return And;
- case OO_Pipe: return Or;
- case OO_Equal: return Assign;
- case OO_Less: return LT;
- case OO_Greater: return GT;
- case OO_PlusEqual: return AddAssign;
- case OO_MinusEqual: return SubAssign;
- case OO_StarEqual: return MulAssign;
- case OO_SlashEqual: return DivAssign;
- case OO_PercentEqual: return RemAssign;
- case OO_CaretEqual: return XorAssign;
- case OO_AmpEqual: return AndAssign;
- case OO_PipeEqual: return OrAssign;
- case OO_LessLess: return Shl;
- case OO_GreaterGreater: return Shr;
- case OO_LessLessEqual: return ShlAssign;
- case OO_GreaterGreaterEqual: return ShrAssign;
- case OO_EqualEqual: return EQ;
- case OO_ExclaimEqual: return NE;
- case OO_LessEqual: return LE;
- case OO_GreaterEqual: return GE;
- case OO_AmpAmp: return LAnd;
- case OO_PipePipe: return LOr;
- case OO_Comma: return Comma;
- case OO_ArrowStar: return PtrMemI;
+ case OO_Plus: return BO_Add;
+ case OO_Minus: return BO_Sub;
+ case OO_Star: return BO_Mul;
+ case OO_Slash: return BO_Div;
+ case OO_Percent: return BO_Rem;
+ case OO_Caret: return BO_Xor;
+ case OO_Amp: return BO_And;
+ case OO_Pipe: return BO_Or;
+ case OO_Equal: return BO_Assign;
+ case OO_Less: return BO_LT;
+ case OO_Greater: return BO_GT;
+ case OO_PlusEqual: return BO_AddAssign;
+ case OO_MinusEqual: return BO_SubAssign;
+ case OO_StarEqual: return BO_MulAssign;
+ case OO_SlashEqual: return BO_DivAssign;
+ case OO_PercentEqual: return BO_RemAssign;
+ case OO_CaretEqual: return BO_XorAssign;
+ case OO_AmpEqual: return BO_AndAssign;
+ case OO_PipeEqual: return BO_OrAssign;
+ case OO_LessLess: return BO_Shl;
+ case OO_GreaterGreater: return BO_Shr;
+ case OO_LessLessEqual: return BO_ShlAssign;
+ case OO_GreaterGreaterEqual: return BO_ShrAssign;
+ case OO_EqualEqual: return BO_EQ;
+ case OO_ExclaimEqual: return BO_NE;
+ case OO_LessEqual: return BO_LE;
+ case OO_GreaterEqual: return BO_GE;
+ case OO_AmpAmp: return BO_LAnd;
+ case OO_PipePipe: return BO_LOr;
+ case OO_Comma: return BO_Comma;
+ case OO_ArrowStar: return BO_PtrMemI;
}
}
@@ -897,9 +1005,6 @@ void InitListExpr::reserveInits(ASTContext &C, unsigned NumInits) {
}
void InitListExpr::resizeInits(ASTContext &C, unsigned NumInits) {
- for (unsigned Idx = NumInits, LastIdx = InitExprs.size();
- Idx < LastIdx; ++Idx)
- InitExprs[Idx]->Destroy(C);
InitExprs.resize(C, NumInits, 0);
}
@@ -963,24 +1068,24 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
switch (UO->getOpcode()) {
default: break;
- case UnaryOperator::PostInc:
- case UnaryOperator::PostDec:
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec: // ++/--
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec: // ++/--
return false; // Not a warning.
- case UnaryOperator::Deref:
+ case UO_Deref:
// Dereferencing a volatile pointer is a side-effect.
if (Ctx.getCanonicalType(getType()).isVolatileQualified())
return false;
break;
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
+ case UO_Real:
+ case UO_Imag:
// accessing a piece of a volatile complex is a side-effect.
if (Ctx.getCanonicalType(UO->getSubExpr()->getType())
.isVolatileQualified())
return false;
break;
- case UnaryOperator::Extension:
+ case UO_Extension:
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
}
Loc = UO->getOperatorLoc();
@@ -994,7 +1099,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
break;
// Consider the RHS of comma for side effects. LHS was checked by
// Sema::CheckCommaOperands.
- case BinaryOperator::Comma:
+ case BO_Comma:
// ((foo = <blah>), 0) is an idiom for hiding the result (and
// lvalue-ness) of an assignment written in a macro.
if (IntegerLiteral *IE =
@@ -1003,8 +1108,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false;
return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
// Consider '||', '&&' to have side effects if the LHS or RHS does.
- case BinaryOperator::LAnd:
- case BinaryOperator::LOr:
+ case BO_LAnd:
+ case BO_LOr:
if (!BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
!BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
return false;
@@ -1137,8 +1242,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If this is a cast to void or a constructor conversion, check the operand.
// Otherwise, the result of the cast is unused.
- if (CE->getCastKind() == CastExpr::CK_ToVoid ||
- CE->getCastKind() == CastExpr::CK_ConstructorConversion)
+ if (CE->getCastKind() == CK_ToVoid ||
+ CE->getCastKind() == CK_ConstructorConversion)
return (cast<CastExpr>(this)->getSubExpr()
->isUnusedResultAWarning(Loc, R1, R2, Ctx));
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
@@ -1287,7 +1392,7 @@ bool Expr::isDefaultArgument() const {
/// expressions.
static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) {
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->getCastKind() == CastExpr::CK_NoOp)
+ if (ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr();
else
break;
@@ -1297,7 +1402,7 @@ static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) {
E = BE->getSubExpr();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->getCastKind() == CastExpr::CK_NoOp)
+ if (ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr();
else
break;
@@ -1314,8 +1419,8 @@ const Expr *Expr::getTemporaryObject() const {
if (const CastExpr *Cast = dyn_cast<CastExpr>(E)) {
// Only user-defined and constructor conversions can produce
// temporary objects.
- if (Cast->getCastKind() != CastExpr::CK_ConstructorConversion &&
- Cast->getCastKind() != CastExpr::CK_UserDefinedConversion)
+ if (Cast->getCastKind() != CK_ConstructorConversion &&
+ Cast->getCastKind() != CK_UserDefinedConversion)
return 0;
// Strip off temporary bindings and no-op casts.
@@ -1323,12 +1428,12 @@ const Expr *Expr::getTemporaryObject() const {
// If this is a constructor conversion, see if we have an object
// construction.
- if (Cast->getCastKind() == CastExpr::CK_ConstructorConversion)
+ if (Cast->getCastKind() == CK_ConstructorConversion)
return dyn_cast<CXXConstructExpr>(Sub);
// If this is a user-defined conversion, see if we have a call to
// a function that itself returns a temporary object.
- if (Cast->getCastKind() == CastExpr::CK_UserDefinedConversion)
+ if (Cast->getCastKind() == CK_UserDefinedConversion)
if (const CallExpr *CE = dyn_cast<CallExpr>(Sub))
if (CE->getCallReturnType()->isRecordType())
return CE;
@@ -1368,15 +1473,20 @@ bool Expr::hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs) {
return false;
}
-bool Expr::isConstantInitializer(ASTContext &Ctx) const {
+bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
// This function is attempting whether an expression is an initializer
// which can be evaluated at compile-time. isEvaluatable handles most
// of the cases, but it can't deal with some initializer-specific
// expressions, and it can't deal with aggregates; we deal with those here,
// and fall back to isEvaluatable for the other cases.
- // FIXME: This function assumes the variable being assigned to
- // isn't a reference type!
+ // If we ever capture reference-binding directly in the AST, we can
+ // kill the second parameter.
+
+ if (IsForRef) {
+ EvalResult Result;
+ return EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects;
+ }
switch (getStmtClass()) {
default: break;
@@ -1384,12 +1494,27 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
case ObjCStringLiteralClass:
case ObjCEncodeExprClass:
return true;
+ case CXXTemporaryObjectExprClass:
+ case CXXConstructExprClass: {
+ const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
+
+ // Only if it's
+ // 1) an application of the trivial default constructor or
+ if (!CE->getConstructor()->isTrivial()) return false;
+ if (!CE->getNumArgs()) return true;
+
+ // 2) an elidable trivial copy construction of an operand which is
+ // itself a constant initializer. Note that we consider the
+ // operand on its own, *not* as a reference binding.
+ return CE->isElidable() &&
+ CE->getArg(0)->isConstantInitializer(Ctx, false);
+ }
case CompoundLiteralExprClass: {
// This handles gcc's extension that allows global initializers like
// "struct x {int x;} x = (struct x) {};".
// FIXME: This accepts other cases it shouldn't!
const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
- return Exp->isConstantInitializer(Ctx);
+ return Exp->isConstantInitializer(Ctx, false);
}
case InitListExprClass: {
// FIXME: This doesn't deal with fields with reference types correctly.
@@ -1398,7 +1523,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
const InitListExpr *Exp = cast<InitListExpr>(this);
unsigned numInits = Exp->getNumInits();
for (unsigned i = 0; i < numInits; i++) {
- if (!Exp->getInit(i)->isConstantInitializer(Ctx))
+ if (!Exp->getInit(i)->isConstantInitializer(Ctx, false))
return false;
}
return true;
@@ -1406,36 +1531,41 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
case ImplicitValueInitExprClass:
return true;
case ParenExprClass:
- return cast<ParenExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<ParenExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, IsForRef);
case UnaryOperatorClass: {
const UnaryOperator* Exp = cast<UnaryOperator>(this);
- if (Exp->getOpcode() == UnaryOperator::Extension)
- return Exp->getSubExpr()->isConstantInitializer(Ctx);
+ if (Exp->getOpcode() == UO_Extension)
+ return Exp->getSubExpr()->isConstantInitializer(Ctx, false);
break;
}
case BinaryOperatorClass: {
// Special case &&foo - &&bar. It would be nice to generalize this somehow
// but this handles the common case.
const BinaryOperator *Exp = cast<BinaryOperator>(this);
- if (Exp->getOpcode() == BinaryOperator::Sub &&
+ if (Exp->getOpcode() == BO_Sub &&
isa<AddrLabelExpr>(Exp->getLHS()->IgnoreParenNoopCasts(Ctx)) &&
isa<AddrLabelExpr>(Exp->getRHS()->IgnoreParenNoopCasts(Ctx)))
return true;
break;
}
+ case CXXFunctionalCastExprClass:
+ case CXXStaticCastExprClass:
case ImplicitCastExprClass:
case CStyleCastExprClass:
// Handle casts with a destination that's a struct or union; this
// deals with both the gcc no-op struct cast extension and the
// cast-to-union extension.
if (getType()->isRecordType())
- return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, false);
// Integer->integer casts can be handled here, which is important for
// things like (int)(&&x-&&y). Scary but true.
if (getType()->isIntegerType() &&
cast<CastExpr>(this)->getSubExpr()->getType()->isIntegerType())
- return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, false);
break;
}
@@ -1508,7 +1638,8 @@ FieldDecl *Expr::getBitField() {
Expr *E = this->IgnoreParens();
while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
+ if (ICE->getValueKind() != VK_RValue &&
+ ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr()->IgnoreParens();
else
break;
@@ -1530,7 +1661,8 @@ bool Expr::refersToVectorElement() const {
const Expr *E = this->IgnoreParens();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
+ if (ICE->getValueKind() != VK_RValue &&
+ ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr()->IgnoreParens();
else
break;
@@ -1773,27 +1905,6 @@ void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs,
memcpy(SubExprs, Exprs, sizeof(Expr *) * NumExprs);
}
-void ShuffleVectorExpr::DoDestroy(ASTContext& C) {
- DestroyChildren(C);
- if (SubExprs) C.Deallocate(SubExprs);
- this->~ShuffleVectorExpr();
- C.Deallocate(this);
-}
-
-void SizeOfAlignOfExpr::DoDestroy(ASTContext& C) {
- // Override default behavior of traversing children. If this has a type
- // operand and the type is a variable-length array, the child iteration
- // will iterate over the size expression. However, this expression belongs
- // to the type, not to this, so we don't want to delete it.
- // We still want to delete this expression.
- if (isArgumentType()) {
- this->~SizeOfAlignOfExpr();
- C.Deallocate(this);
- }
- else
- Expr::DoDestroy(C);
-}
-
//===----------------------------------------------------------------------===//
// DesignatedInitExpr
//===----------------------------------------------------------------------===//
@@ -1878,8 +1989,6 @@ DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
void DesignatedInitExpr::setDesignators(ASTContext &C,
const Designator *Desigs,
unsigned NumDesigs) {
- DestroyDesignators(C);
-
Designators = new (C) Designator[NumDesigs];
NumDesignators = NumDesigs;
for (unsigned I = 0; I != NumDesigs; ++I)
@@ -1950,23 +2059,10 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
std::copy(First, Last, NewDesignators + Idx);
std::copy(Designators + Idx + 1, Designators + NumDesignators,
NewDesignators + Idx + NumNewDesignators);
- DestroyDesignators(C);
Designators = NewDesignators;
NumDesignators = NumDesignators - 1 + NumNewDesignators;
}
-void DesignatedInitExpr::DoDestroy(ASTContext &C) {
- DestroyDesignators(C);
- Expr::DoDestroy(C);
-}
-
-void DesignatedInitExpr::DestroyDesignators(ASTContext &C) {
- for (unsigned I = 0; I != NumDesignators; ++I)
- Designators[I].~Designator();
- C.Deallocate(Designators);
- Designators = 0;
-}
-
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Expr **exprs, unsigned nexprs,
SourceLocation rparenloc)
@@ -1980,13 +2076,6 @@ ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Exprs[i] = exprs[i];
}
-void ParenListExpr::DoDestroy(ASTContext& C) {
- DestroyChildren(C);
- if (Exprs) C.Deallocate(Exprs);
- this->~ParenListExpr();
- C.Deallocate(this);
-}
-
//===----------------------------------------------------------------------===//
// ExprIterator.
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index c2548eca659e..0a101300d8fa 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -118,14 +118,6 @@ void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray,
}
-void CXXNewExpr::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- if (SubExprs)
- C.Deallocate(SubExprs);
- this->~CXXNewExpr();
- C.Deallocate((void*)this);
-}
-
Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator CXXNewExpr::child_end() {
return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs();
@@ -167,8 +159,9 @@ UnresolvedLookupExpr *
UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange, DeclarationName Name,
- SourceLocation NameLoc, bool ADL,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ bool ADL,
const TemplateArgumentListInfo &Args,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
@@ -179,8 +172,8 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
= new (Mem) UnresolvedLookupExpr(C,
Dependent ? C.DependentTy : C.OverloadTy,
Dependent, NamingClass,
- Qualifier, QualifierRange,
- Name, NameLoc, ADL,
+ Qualifier, QualifierRange, NameInfo,
+ ADL,
/*Overload*/ true,
/*ExplicitTemplateArgs*/ true,
Begin, End);
@@ -204,14 +197,14 @@ UnresolvedLookupExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) {
OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T,
bool Dependent, NestedNameSpecifier *Qualifier,
- SourceRange QRange, DeclarationName Name,
- SourceLocation NameLoc, bool HasTemplateArgs,
+ SourceRange QRange,
+ const DeclarationNameInfo &NameInfo,
+ bool HasTemplateArgs,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
: Expr(K, T, Dependent, Dependent),
- Results(0), NumResults(0), Name(Name), Qualifier(Qualifier),
- QualifierRange(QRange), NameLoc(NameLoc),
- HasExplicitTemplateArgs(HasTemplateArgs)
+ Results(0), NumResults(0), NameInfo(NameInfo), Qualifier(Qualifier),
+ QualifierRange(QRange), HasExplicitTemplateArgs(HasTemplateArgs)
{
initializeResults(C, Begin, End);
}
@@ -270,8 +263,7 @@ DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::Create(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args);
@@ -280,8 +272,7 @@ DependentScopeDeclRefExpr::Create(ASTContext &C,
DependentScopeDeclRefExpr *DRE
= new (Mem) DependentScopeDeclRefExpr(C.DependentTy,
Qualifier, QualifierRange,
- Name, NameLoc,
- Args != 0);
+ NameInfo, Args != 0);
if (Args)
reinterpret_cast<ExplicitTemplateArgumentList*>(DRE+1)
@@ -299,7 +290,7 @@ DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
void *Mem = C.Allocate(size);
return new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
- DeclarationName(),SourceLocation(),
+ DeclarationNameInfo(),
NumTemplateArgs != 0);
}
@@ -395,6 +386,118 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
C.getBaseElementType(QueriedType)->getAs<RecordType>())
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
return false;
+ // TODO: Propagate nothrowness for implicitly declared special members.
+ case UTT_HasNothrowAssign:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If type is const qualified or is a reference type then the
+ // trait is false. Otherwise if __has_trivial_assign (type)
+ // is true then the trait is true, else if type is a cv class
+ // or union type with copy assignment operators that are known
+ // not to throw an exception then the trait is true, else it is
+ // false.
+ if (C.getBaseElementType(QueriedType).isConstQualified())
+ return false;
+ if (QueriedType->isReferenceType())
+ return false;
+ if (QueriedType->isPODType())
+ return true;
+ if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
+ CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialCopyAssignment())
+ return true;
+
+ bool FoundAssign = false;
+ bool AllNoThrow = true;
+ DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
+ DeclContext::lookup_const_iterator Op, OpEnd;
+ for (llvm::tie(Op, OpEnd) = RD->lookup(Name);
+ Op != OpEnd; ++Op) {
+ CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
+ if (Operator->isCopyAssignmentOperator()) {
+ FoundAssign = true;
+ const FunctionProtoType *CPT
+ = Operator->getType()->getAs<FunctionProtoType>();
+ if (!CPT->hasEmptyExceptionSpec()) {
+ AllNoThrow = false;
+ break;
+ }
+ }
+ }
+
+ return FoundAssign && AllNoThrow;
+ }
+ return false;
+ case UTT_HasNothrowCopy:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If __has_trivial_copy (type) is true then the trait is true, else
+ // if type is a cv class or union type with copy constructors that are
+ // known not to throw an exception then the trait is true, else it is
+ // false.
+ if (QueriedType->isPODType() || QueriedType->isReferenceType())
+ return true;
+ if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialCopyConstructor())
+ return true;
+
+ bool FoundConstructor = false;
+ bool AllNoThrow = true;
+ unsigned FoundTQs;
+ DeclarationName ConstructorName
+ = C.DeclarationNames.getCXXConstructorName(
+ C.getCanonicalType(QueriedType));
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = RD->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isCopyConstructor(FoundTQs)) {
+ FoundConstructor = true;
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ if (!CPT->hasEmptyExceptionSpec()) {
+ AllNoThrow = false;
+ break;
+ }
+ }
+ }
+
+ return FoundConstructor && AllNoThrow;
+ }
+ return false;
+ case UTT_HasNothrowConstructor:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If __has_trivial_constructor (type) is true then the trait is
+ // true, else if type is a cv class or union type (or array
+ // thereof) with a default constructor that is known not to
+ // throw an exception then the trait is true, else it is false.
+ if (QueriedType->isPODType())
+ return true;
+ if (const RecordType *RT =
+ C.getBaseElementType(QueriedType)->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialConstructor())
+ return true;
+
+ if (CXXConstructorDecl *Constructor = RD->getDefaultConstructor()) {
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ // TODO: check whether evaluating default arguments can throw.
+ // For now, we'll be conservative and assume that they can throw.
+ if (CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0)
+ return true;
+ }
+ }
+ return false;
+ case UTT_HasVirtualDestructor:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If type is a class type with a virtual destructor ([class.dtor])
+ // then the trait is true, else it is false.
+ if (const RecordType *Record = QueriedType->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ if (CXXDestructorDecl *Destructor = RD->getDestructor())
+ return Destructor->isVirtual();
+ }
+ return false;
}
}
@@ -468,6 +571,100 @@ const char *CXXNamedCastExpr::getCastName() const {
}
}
+CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXStaticCastExpr *E =
+ new (Buffer) CXXStaticCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXDynamicCastExpr *E =
+ new (Buffer) CXXDynamicCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXReinterpretCastExpr *E =
+ new (Buffer) CXXReinterpretCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, Expr *Op,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ return new (C) CXXConstCastExpr(T, Op, WrittenTy, L);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) {
+ return new (C) CXXConstCastExpr(EmptyShell());
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::Create(ASTContext &C, QualType T,
+ TypeSourceInfo *Written, SourceLocation L,
+ CastKind K, Expr *Op, const CXXCastPath *BasePath,
+ SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXFunctionalCastExpr *E =
+ new (Buffer) CXXFunctionalCastExpr(T, Written, L, K, Op, PathSize, R);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
+}
+
+
CXXDefaultArgExpr *
CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc,
ParmVarDecl *Param, Expr *SubExpr) {
@@ -476,23 +673,11 @@ CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc,
SubExpr);
}
-void CXXDefaultArgExpr::DoDestroy(ASTContext &C) {
- if (Param.getInt())
- getExpr()->Destroy(C);
- this->~CXXDefaultArgExpr();
- C.Deallocate(this);
-}
-
CXXTemporary *CXXTemporary::Create(ASTContext &C,
const CXXDestructorDecl *Destructor) {
return new (C) CXXTemporary(Destructor);
}
-void CXXTemporary::Destroy(ASTContext &Ctx) {
- this->~CXXTemporary();
- Ctx.Deallocate(this);
-}
-
CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C,
CXXTemporary *Temp,
Expr* SubExpr) {
@@ -502,25 +687,6 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C,
return new (C) CXXBindTemporaryExpr(Temp, SubExpr);
}
-void CXXBindTemporaryExpr::DoDestroy(ASTContext &C) {
- Temp->Destroy(C);
- this->~CXXBindTemporaryExpr();
- C.Deallocate(this);
-}
-
-CXXBindReferenceExpr *CXXBindReferenceExpr::Create(ASTContext &C, Expr *SubExpr,
- bool ExtendsLifetime,
- bool RequiresTemporaryCopy) {
- return new (C) CXXBindReferenceExpr(SubExpr,
- ExtendsLifetime,
- RequiresTemporaryCopy);
-}
-
-void CXXBindReferenceExpr::DoDestroy(ASTContext &C) {
- this->~CXXBindReferenceExpr();
- C.Deallocate(this);
-}
-
CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
CXXConstructorDecl *Cons,
QualType writtenTy,
@@ -569,14 +735,6 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
}
}
-void CXXConstructExpr::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- if (Args)
- C.Deallocate(Args);
- this->~CXXConstructExpr();
- C.Deallocate(this);
-}
-
CXXExprWithTemporaries::CXXExprWithTemporaries(ASTContext &C,
Expr *subexpr,
CXXTemporary **temps,
@@ -605,16 +763,6 @@ CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C,
return new (C) CXXExprWithTemporaries(C, SubExpr, Temps, NumTemps);
}
-void CXXExprWithTemporaries::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- if (Temps)
- C.Deallocate(Temps);
- this->~CXXExprWithTemporaries();
- C.Deallocate(this);
-}
-
-CXXExprWithTemporaries::~CXXExprWithTemporaries() {}
-
// CXXBindTemporaryExpr
Stmt::child_iterator CXXBindTemporaryExpr::child_begin() {
return &SubExpr;
@@ -624,15 +772,6 @@ Stmt::child_iterator CXXBindTemporaryExpr::child_end() {
return &SubExpr + 1;
}
-// CXXBindReferenceExpr
-Stmt::child_iterator CXXBindReferenceExpr::child_begin() {
- return &SubExpr;
-}
-
-Stmt::child_iterator CXXBindReferenceExpr::child_end() {
- return &SubExpr + 1;
-}
-
// CXXConstructExpr
Stmt::child_iterator CXXConstructExpr::child_begin() {
return &Args[0];
@@ -705,8 +844,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
Base(Base), BaseType(BaseType), IsArrow(IsArrow),
@@ -714,9 +852,9 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
- Member(Member), MemberLoc(MemberLoc) {
+ MemberNameInfo(MemberNameInfo) {
if (TemplateArgs)
- getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs);
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
}
CXXDependentScopeMemberExpr *
@@ -726,15 +864,14 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
if (!TemplateArgs)
return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType,
IsArrow, OperatorLoc,
Qualifier, QualifierRange,
FirstQualifierFoundInScope,
- Member, MemberLoc);
+ MemberNameInfo);
std::size_t size = sizeof(CXXDependentScopeMemberExpr);
if (TemplateArgs)
@@ -745,7 +882,7 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C,
IsArrow, OperatorLoc,
Qualifier, QualifierRange,
FirstQualifierFoundInScope,
- Member, MemberLoc, TemplateArgs);
+ MemberNameInfo, TemplateArgs);
}
CXXDependentScopeMemberExpr *
@@ -755,8 +892,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(),
0, SourceLocation(), 0,
SourceRange(), 0,
- DeclarationName(),
- SourceLocation());
+ DeclarationNameInfo());
std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
@@ -765,8 +901,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
= new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(),
0, SourceLocation(), 0,
SourceRange(), 0,
- DeclarationName(),
- SourceLocation(), 0);
+ DeclarationNameInfo(), 0);
E->HasExplicitTemplateArgs = true;
return E;
}
@@ -789,13 +924,12 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, QualType T,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName MemberName,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
: OverloadExpr(UnresolvedMemberExprClass, C, T, Dependent,
- Qualifier, QualifierRange, MemberName, MemberLoc,
+ Qualifier, QualifierRange, MemberNameInfo,
TemplateArgs != 0, Begin, End),
IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
@@ -810,8 +944,7 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
@@ -824,7 +957,7 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
Dependent ? C.DependentTy : C.OverloadTy,
Dependent, HasUnresolvedUsing, Base, BaseType,
IsArrow, OperatorLoc, Qualifier, QualifierRange,
- Member, MemberLoc, TemplateArgs, Begin, End);
+ MemberNameInfo, TemplateArgs, Begin, End);
}
UnresolvedMemberExpr *
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 60ac347c50fb..d7e38ebbf5c9 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -111,20 +111,20 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// C++ [expr.unary.op]p1: The unary * operator performs indirection:
// [...] the result is an lvalue referring to the object or function
// to which the expression points.
- case UnaryOperator::Deref:
+ case UO_Deref:
return Cl::CL_LValue;
// GNU extensions, simply look through them.
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
- case UnaryOperator::Extension:
+ case UO_Real:
+ case UO_Imag:
+ case UO_Extension:
return ClassifyInternal(Ctx, cast<UnaryOperator>(E)->getSubExpr());
// C++ [expr.pre.incr]p1: The result is the updated operand; it is an
// lvalue, [...]
// Not so in C.
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec:
+ case UO_PreInc:
+ case UO_PreDec:
return Lang.CPlusPlus ? Cl::CL_LValue : Cl::CL_PRValue;
default:
@@ -134,10 +134,16 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// Implicit casts are lvalues if they're lvalue casts. Other than that, we
// only specifically record class temporaries.
case Expr::ImplicitCastExprClass:
- if (cast<ImplicitCastExpr>(E)->isLvalueCast())
+ switch (cast<ImplicitCastExpr>(E)->getValueKind()) {
+ case VK_RValue:
+ return Lang.CPlusPlus && E->getType()->isRecordType() ?
+ Cl::CL_ClassTemporary : Cl::CL_PRValue;
+ case VK_LValue:
return Cl::CL_LValue;
- return Lang.CPlusPlus && E->getType()->isRecordType() ?
- Cl::CL_ClassTemporary : Cl::CL_PRValue;
+ case VK_XValue:
+ return Cl::CL_XValue;
+ }
+ llvm_unreachable("Invalid value category of implicit cast.");
// C++ [expr.prim.general]p4: The presence of parentheses does not affect
// whether the expression is an lvalue.
@@ -223,6 +229,10 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
// In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
// lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
// special-case this.
+
+ if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
+ return Cl::CL_MemberFunction;
+
bool islvalue;
if (const NonTypeTemplateParmDecl *NTTParm =
dyn_cast<NonTypeTemplateParmDecl>(D))
@@ -315,19 +325,19 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) {
// C++ [expr.comma]p1: the result is of the same value category as its right
// operand, [...].
- if (E->getOpcode() == BinaryOperator::Comma)
+ if (E->getOpcode() == BO_Comma)
return ClassifyInternal(Ctx, E->getRHS());
// C++ [expr.mptr.oper]p6: The result of a .* expression whose second operand
// is a pointer to a data member is of the same value category as its first
// operand.
- if (E->getOpcode() == BinaryOperator::PtrMemD)
+ if (E->getOpcode() == BO_PtrMemD)
return E->getType()->isFunctionType() ? Cl::CL_MemberFunction :
ClassifyInternal(Ctx, E->getLHS());
// C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its
// second operand is a pointer to data member and a prvalue otherwise.
- if (E->getOpcode() == BinaryOperator::PtrMemI)
+ if (E->getOpcode() == BO_PtrMemI)
return E->getType()->isFunctionType() ?
Cl::CL_MemberFunction : Cl::CL_LValue;
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 3c9742033265..7347f5a43e17 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -337,7 +337,7 @@ public:
default:
return false;
- case CastExpr::CK_NoOp:
+ case CK_NoOp:
return Visit(E->getSubExpr());
}
}
@@ -481,8 +481,8 @@ static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) {
}
bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() != BinaryOperator::Add &&
- E->getOpcode() != BinaryOperator::Sub)
+ if (E->getOpcode() != BO_Add &&
+ E->getOpcode() != BO_Sub)
return false;
const Expr *PExp = E->getLHS();
@@ -512,7 +512,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
else
SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
- if (E->getOpcode() == BinaryOperator::Add)
+ if (E->getOpcode() == BO_Add)
Result.Offset += AdditionalOffset * SizeOfPointee;
else
Result.Offset -= AdditionalOffset * SizeOfPointee;
@@ -532,7 +532,7 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
default:
break;
- case CastExpr::CK_Unknown: {
+ case CK_Unknown: {
// FIXME: The handling for CK_Unknown is ugly/shouldn't be necessary!
// Check for pointer->pointer cast
@@ -561,14 +561,14 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
break;
}
- case CastExpr::CK_NoOp:
- case CastExpr::CK_BitCast:
- case CastExpr::CK_LValueBitCast:
- case CastExpr::CK_AnyPointerToObjCPointerCast:
- case CastExpr::CK_AnyPointerToBlockPointerCast:
+ case CK_NoOp:
+ case CK_BitCast:
+ case CK_LValueBitCast:
+ case CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
return Visit(SubExpr);
- case CastExpr::CK_IntegralToPointer: {
+ case CK_IntegralToPointer: {
APValue Value;
if (!EvaluateIntegerOrLValue(SubExpr, Value, Info))
break;
@@ -585,8 +585,8 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
return true;
}
}
- case CastExpr::CK_ArrayToPointerDecay:
- case CastExpr::CK_FunctionToPointerDecay:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
return EvaluateLValue(SubExpr, Result, Info);
}
@@ -1008,8 +1008,11 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
VD->setEvaluatingValue();
- if (Visit(const_cast<Expr*>(Init))) {
+ Expr::EvalResult EResult;
+ if (Init->Evaluate(EResult, Info.Ctx) && !EResult.HasSideEffects &&
+ EResult.Val.isInt()) {
// Cache the evaluated value in the variable declaration.
+ Result = EResult.Val;
VD->setEvaluatedValue(Result);
return true;
}
@@ -1106,7 +1109,7 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(CallExpr *E) {
QualType T = GetObjectType(LVBase);
if (T.isNull() ||
T->isIncompleteType() ||
- !T->isObjectType() ||
+ T->isFunctionType() ||
T->isVariablyModifiedType() ||
T->isDependentType())
return false;
@@ -1161,7 +1164,7 @@ bool IntExprEvaluator::VisitCallExpr(CallExpr *E) {
}
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() == BinaryOperator::Comma) {
+ if (E->getOpcode() == BO_Comma) {
if (!Visit(E->getRHS()))
return false;
@@ -1181,11 +1184,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (HandleConversionToBool(E->getLHS(), lhsResult, Info)) {
// We were able to evaluate the LHS, see if we can get away with not
// evaluating the RHS: 0 && X -> 0, 1 || X -> 1
- if (lhsResult == (E->getOpcode() == BinaryOperator::LOr))
+ if (lhsResult == (E->getOpcode() == BO_LOr))
return Success(lhsResult, E);
if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
- if (E->getOpcode() == BinaryOperator::LOr)
+ if (E->getOpcode() == BO_LOr)
return Success(lhsResult || rhsResult, E);
else
return Success(lhsResult && rhsResult, E);
@@ -1194,8 +1197,8 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
// We can't evaluate the LHS; however, sometimes the result
// is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
- if (rhsResult == (E->getOpcode() == BinaryOperator::LOr) ||
- !rhsResult == (E->getOpcode() == BinaryOperator::LAnd)) {
+ if (rhsResult == (E->getOpcode() == BO_LOr) ||
+ !rhsResult == (E->getOpcode() == BO_LAnd)) {
// Since we weren't able to evaluate the left hand side, it
// must have had side effects.
Info.EvalResult.HasSideEffects = true;
@@ -1227,11 +1230,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat::cmpResult CR_i =
LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag());
- if (E->getOpcode() == BinaryOperator::EQ)
+ if (E->getOpcode() == BO_EQ)
return Success((CR_r == APFloat::cmpEqual &&
CR_i == APFloat::cmpEqual), E);
else {
- assert(E->getOpcode() == BinaryOperator::NE &&
+ assert(E->getOpcode() == BO_NE &&
"Invalid complex comparison.");
return Success(((CR_r == APFloat::cmpGreaterThan ||
CR_r == APFloat::cmpLessThan ||
@@ -1241,11 +1244,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
CR_i == APFloat::cmpUnordered)), E);
}
} else {
- if (E->getOpcode() == BinaryOperator::EQ)
+ if (E->getOpcode() == BO_EQ)
return Success((LHS.getComplexIntReal() == RHS.getComplexIntReal() &&
LHS.getComplexIntImag() == RHS.getComplexIntImag()), E);
else {
- assert(E->getOpcode() == BinaryOperator::NE &&
+ assert(E->getOpcode() == BO_NE &&
"Invalid compex comparison.");
return Success((LHS.getComplexIntReal() != RHS.getComplexIntReal() ||
LHS.getComplexIntImag() != RHS.getComplexIntImag()), E);
@@ -1268,18 +1271,18 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default:
assert(0 && "Invalid binary operator!");
- case BinaryOperator::LT:
+ case BO_LT:
return Success(CR == APFloat::cmpLessThan, E);
- case BinaryOperator::GT:
+ case BO_GT:
return Success(CR == APFloat::cmpGreaterThan, E);
- case BinaryOperator::LE:
+ case BO_LE:
return Success(CR == APFloat::cmpLessThan || CR == APFloat::cmpEqual, E);
- case BinaryOperator::GE:
+ case BO_GE:
return Success(CR == APFloat::cmpGreaterThan || CR == APFloat::cmpEqual,
E);
- case BinaryOperator::EQ:
+ case BO_EQ:
return Success(CR == APFloat::cmpEqual, E);
- case BinaryOperator::NE:
+ case BO_NE:
return Success(CR == APFloat::cmpGreaterThan
|| CR == APFloat::cmpLessThan
|| CR == APFloat::cmpUnordered, E);
@@ -1287,7 +1290,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
}
if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
- if (E->getOpcode() == BinaryOperator::Sub || E->isEqualityOp()) {
+ if (E->getOpcode() == BO_Sub || E->isEqualityOp()) {
LValue LHSValue;
if (!EvaluatePointer(E->getLHS(), LHSValue, Info))
return false;
@@ -1306,7 +1309,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
bool bres;
if (!EvalPointerValueAsBool(LHSValue, bres))
return false;
- return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E);
+ return Success(bres ^ (E->getOpcode() == BO_EQ), E);
} else if (RHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
@@ -1315,10 +1318,10 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
bool bres;
if (!EvalPointerValueAsBool(RHSValue, bres))
return false;
- return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E);
+ return Success(bres ^ (E->getOpcode() == BO_EQ), E);
}
- if (E->getOpcode() == BinaryOperator::Sub) {
+ if (E->getOpcode() == BO_Sub) {
QualType Type = E->getLHS()->getType();
QualType ElementType = Type->getAs<PointerType>()->getPointeeType();
@@ -1331,7 +1334,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
return Success(Diff / ElementSize, E);
}
bool Result;
- if (E->getOpcode() == BinaryOperator::EQ) {
+ if (E->getOpcode() == BO_EQ) {
Result = LHSValue.getLValueOffset() == RHSValue.getLValueOffset();
} else {
Result = LHSValue.getLValueOffset() != RHSValue.getLValueOffset();
@@ -1359,7 +1362,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
CharUnits Offset = Result.getLValueOffset();
CharUnits AdditionalOffset = CharUnits::fromQuantity(
RHSVal.getInt().getZExtValue());
- if (E->getOpcode() == BinaryOperator::Add)
+ if (E->getOpcode() == BO_Add)
Offset += AdditionalOffset;
else
Offset -= AdditionalOffset;
@@ -1368,7 +1371,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
}
// Handle cases like 4 + (unsigned long)&a
- if (E->getOpcode() == BinaryOperator::Add &&
+ if (E->getOpcode() == BO_Add &&
RHSVal.isLValue() && Result.isInt()) {
CharUnits Offset = RHSVal.getLValueOffset();
Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue());
@@ -1385,38 +1388,38 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default:
return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
- case BinaryOperator::Mul: return Success(Result.getInt() * RHS, E);
- case BinaryOperator::Add: return Success(Result.getInt() + RHS, E);
- case BinaryOperator::Sub: return Success(Result.getInt() - RHS, E);
- case BinaryOperator::And: return Success(Result.getInt() & RHS, E);
- case BinaryOperator::Xor: return Success(Result.getInt() ^ RHS, E);
- case BinaryOperator::Or: return Success(Result.getInt() | RHS, E);
- case BinaryOperator::Div:
+ case BO_Mul: return Success(Result.getInt() * RHS, E);
+ case BO_Add: return Success(Result.getInt() + RHS, E);
+ case BO_Sub: return Success(Result.getInt() - RHS, E);
+ case BO_And: return Success(Result.getInt() & RHS, E);
+ case BO_Xor: return Success(Result.getInt() ^ RHS, E);
+ case BO_Or: return Success(Result.getInt() | RHS, E);
+ case BO_Div:
if (RHS == 0)
return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
return Success(Result.getInt() / RHS, E);
- case BinaryOperator::Rem:
+ case BO_Rem:
if (RHS == 0)
return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
return Success(Result.getInt() % RHS, E);
- case BinaryOperator::Shl: {
+ case BO_Shl: {
// FIXME: Warn about out of range shift amounts!
unsigned SA =
(unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
return Success(Result.getInt() << SA, E);
}
- case BinaryOperator::Shr: {
+ case BO_Shr: {
unsigned SA =
(unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
return Success(Result.getInt() >> SA, E);
}
- case BinaryOperator::LT: return Success(Result.getInt() < RHS, E);
- case BinaryOperator::GT: return Success(Result.getInt() > RHS, E);
- case BinaryOperator::LE: return Success(Result.getInt() <= RHS, E);
- case BinaryOperator::GE: return Success(Result.getInt() >= RHS, E);
- case BinaryOperator::EQ: return Success(Result.getInt() == RHS, E);
- case BinaryOperator::NE: return Success(Result.getInt() != RHS, E);
+ case BO_LT: return Success(Result.getInt() < RHS, E);
+ case BO_GT: return Success(Result.getInt() > RHS, E);
+ case BO_LE: return Success(Result.getInt() <= RHS, E);
+ case BO_GE: return Success(Result.getInt() >= RHS, E);
+ case BO_EQ: return Success(Result.getInt() == RHS, E);
+ case BO_NE: return Success(Result.getInt() != RHS, E);
}
}
@@ -1573,20 +1576,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) {
}
bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
- // Special case unary operators that do not need their subexpression
- // evaluated. offsetof/sizeof/alignof are all special.
- if (E->isOffsetOfOp()) {
- // The AST for offsetof is defined in such a way that we can just
- // directly Evaluate it as an l-value.
- LValue LV;
- if (!EvaluateLValue(E->getSubExpr(), LV, Info))
- return false;
- if (LV.getLValueBase())
- return false;
- return Success(LV.getLValueOffset().getQuantity(), E);
- }
-
- if (E->getOpcode() == UnaryOperator::LNot) {
+ if (E->getOpcode() == UO_LNot) {
// LNot's operand isn't necessarily an integer, so we handle it specially.
bool bres;
if (!HandleConversionToBool(E->getSubExpr(), bres, Info))
@@ -1607,17 +1597,17 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
// Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
// See C99 6.6p3.
return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
- case UnaryOperator::Extension:
+ case UO_Extension:
// FIXME: Should extension allow i-c-e extension expressions in its scope?
// If so, we could clear the diagnostic ID.
return true;
- case UnaryOperator::Plus:
+ case UO_Plus:
// The result is always just the subexpr.
return true;
- case UnaryOperator::Minus:
+ case UO_Minus:
if (!Result.isInt()) return false;
return Success(-Result.getInt(), E);
- case UnaryOperator::Not:
+ case UO_Not:
if (!Result.isInt()) return false;
return Success(~Result.getInt(), E);
}
@@ -1855,23 +1845,35 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {
- ComplexValue CV;
- if (!EvaluateComplex(E->getSubExpr(), CV, Info))
- return false;
- Result = CV.FloatReal;
- return true;
+ if (E->getSubExpr()->getType()->isAnyComplexType()) {
+ ComplexValue CV;
+ if (!EvaluateComplex(E->getSubExpr(), CV, Info))
+ return false;
+ Result = CV.FloatReal;
+ return true;
+ }
+
+ return Visit(E->getSubExpr());
}
bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
- ComplexValue CV;
- if (!EvaluateComplex(E->getSubExpr(), CV, Info))
- return false;
- Result = CV.FloatImag;
+ if (E->getSubExpr()->getType()->isAnyComplexType()) {
+ ComplexValue CV;
+ if (!EvaluateComplex(E->getSubExpr(), CV, Info))
+ return false;
+ Result = CV.FloatImag;
+ return true;
+ }
+
+ if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
+ Info.EvalResult.HasSideEffects = true;
+ const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType());
+ Result = llvm::APFloat::getZero(Sem);
return true;
}
bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
- if (E->getOpcode() == UnaryOperator::Deref)
+ if (E->getOpcode() == UO_Deref)
return false;
if (!EvaluateFloat(E->getSubExpr(), Result, Info))
@@ -1879,16 +1881,16 @@ bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
switch (E->getOpcode()) {
default: return false;
- case UnaryOperator::Plus:
+ case UO_Plus:
return true;
- case UnaryOperator::Minus:
+ case UO_Minus:
Result.changeSign();
return true;
}
}
bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() == BinaryOperator::Comma) {
+ if (E->getOpcode() == BO_Comma) {
if (!EvaluateFloat(E->getRHS(), Result, Info))
return false;
@@ -1910,16 +1912,16 @@ bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default: return false;
- case BinaryOperator::Mul:
+ case BO_Mul:
Result.multiply(RHS, APFloat::rmNearestTiesToEven);
return true;
- case BinaryOperator::Add:
+ case BO_Add:
Result.add(RHS, APFloat::rmNearestTiesToEven);
return true;
- case BinaryOperator::Sub:
+ case BO_Sub:
Result.subtract(RHS, APFloat::rmNearestTiesToEven);
return true;
- case BinaryOperator::Div:
+ case BO_Div:
Result.divide(RHS, APFloat::rmNearestTiesToEven);
return true;
}
@@ -1990,138 +1992,142 @@ public:
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
- bool VisitImaginaryLiteral(ImaginaryLiteral *E) {
- Expr* SubExpr = E->getSubExpr();
+ bool VisitImaginaryLiteral(ImaginaryLiteral *E);
- if (SubExpr->getType()->isRealFloatingType()) {
- Result.makeComplexFloat();
- APFloat &Imag = Result.FloatImag;
- if (!EvaluateFloat(SubExpr, Imag, Info))
- return false;
+ bool VisitCastExpr(CastExpr *E);
+
+ bool VisitBinaryOperator(const BinaryOperator *E);
+ bool VisitChooseExpr(const ChooseExpr *E)
+ { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+ bool VisitUnaryExtension(const UnaryOperator *E)
+ { return Visit(E->getSubExpr()); }
+ // FIXME Missing: unary +/-/~, binary div, ImplicitValueInitExpr,
+ // conditional ?:, comma
+};
+} // end anonymous namespace
+
+static bool EvaluateComplex(const Expr *E, ComplexValue &Result,
+ EvalInfo &Info) {
+ assert(E->getType()->isAnyComplexType());
+ return ComplexExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+}
+
+bool ComplexExprEvaluator::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+ Expr* SubExpr = E->getSubExpr();
+
+ if (SubExpr->getType()->isRealFloatingType()) {
+ Result.makeComplexFloat();
+ APFloat &Imag = Result.FloatImag;
+ if (!EvaluateFloat(SubExpr, Imag, Info))
+ return false;
- Result.FloatReal = APFloat(Imag.getSemantics());
+ Result.FloatReal = APFloat(Imag.getSemantics());
+ return true;
+ } else {
+ assert(SubExpr->getType()->isIntegerType() &&
+ "Unexpected imaginary literal.");
+
+ Result.makeComplexInt();
+ APSInt &Imag = Result.IntImag;
+ if (!EvaluateInteger(SubExpr, Imag, Info))
+ return false;
+
+ Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned());
+ return true;
+ }
+}
+
+bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) {
+ Expr* SubExpr = E->getSubExpr();
+ QualType EltType = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType SubType = SubExpr->getType();
+
+ if (SubType->isRealFloatingType()) {
+ APFloat &Real = Result.FloatReal;
+ if (!EvaluateFloat(SubExpr, Real, Info))
+ return false;
+
+ if (EltType->isRealFloatingType()) {
+ Result.makeComplexFloat();
+ Real = HandleFloatToFloatCast(EltType, SubType, Real, Info.Ctx);
+ Result.FloatImag = APFloat(Real.getSemantics());
return true;
} else {
- assert(SubExpr->getType()->isIntegerType() &&
- "Unexpected imaginary literal.");
-
Result.makeComplexInt();
- APSInt &Imag = Result.IntImag;
- if (!EvaluateInteger(SubExpr, Imag, Info))
- return false;
-
- Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned());
+ Result.IntReal = HandleFloatToIntCast(EltType, SubType, Real, Info.Ctx);
+ Result.IntImag = APSInt(Result.IntReal.getBitWidth(),
+ !Result.IntReal.isSigned());
return true;
}
- }
+ } else if (SubType->isIntegerType()) {
+ APSInt &Real = Result.IntReal;
+ if (!EvaluateInteger(SubExpr, Real, Info))
+ return false;
- bool VisitCastExpr(CastExpr *E) {
- Expr* SubExpr = E->getSubExpr();
- QualType EltType = E->getType()->getAs<ComplexType>()->getElementType();
- QualType SubType = SubExpr->getType();
+ if (EltType->isRealFloatingType()) {
+ Result.makeComplexFloat();
+ Result.FloatReal
+ = HandleIntToFloatCast(EltType, SubType, Real, Info.Ctx);
+ Result.FloatImag = APFloat(Result.FloatReal.getSemantics());
+ return true;
+ } else {
+ Result.makeComplexInt();
+ Real = HandleIntToIntCast(EltType, SubType, Real, Info.Ctx);
+ Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned());
+ return true;
+ }
+ } else if (const ComplexType *CT = SubType->getAs<ComplexType>()) {
+ if (!Visit(SubExpr))
+ return false;
- if (SubType->isRealFloatingType()) {
- APFloat &Real = Result.FloatReal;
- if (!EvaluateFloat(SubExpr, Real, Info))
- return false;
+ QualType SrcType = CT->getElementType();
+ if (Result.isComplexFloat()) {
if (EltType->isRealFloatingType()) {
Result.makeComplexFloat();
- Real = HandleFloatToFloatCast(EltType, SubType, Real, Info.Ctx);
- Result.FloatImag = APFloat(Real.getSemantics());
+ Result.FloatReal = HandleFloatToFloatCast(EltType, SrcType,
+ Result.FloatReal,
+ Info.Ctx);
+ Result.FloatImag = HandleFloatToFloatCast(EltType, SrcType,
+ Result.FloatImag,
+ Info.Ctx);
return true;
} else {
Result.makeComplexInt();
- Result.IntReal = HandleFloatToIntCast(EltType, SubType, Real, Info.Ctx);
- Result.IntImag = APSInt(Result.IntReal.getBitWidth(),
- !Result.IntReal.isSigned());
+ Result.IntReal = HandleFloatToIntCast(EltType, SrcType,
+ Result.FloatReal,
+ Info.Ctx);
+ Result.IntImag = HandleFloatToIntCast(EltType, SrcType,
+ Result.FloatImag,
+ Info.Ctx);
return true;
}
- } else if (SubType->isIntegerType()) {
- APSInt &Real = Result.IntReal;
- if (!EvaluateInteger(SubExpr, Real, Info))
- return false;
-
+ } else {
+ assert(Result.isComplexInt() && "Invalid evaluate result.");
if (EltType->isRealFloatingType()) {
Result.makeComplexFloat();
- Result.FloatReal
- = HandleIntToFloatCast(EltType, SubType, Real, Info.Ctx);
- Result.FloatImag = APFloat(Result.FloatReal.getSemantics());
+ Result.FloatReal = HandleIntToFloatCast(EltType, SrcType,
+ Result.IntReal,
+ Info.Ctx);
+ Result.FloatImag = HandleIntToFloatCast(EltType, SrcType,
+ Result.IntImag,
+ Info.Ctx);
return true;
} else {
Result.makeComplexInt();
- Real = HandleIntToIntCast(EltType, SubType, Real, Info.Ctx);
- Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned());
+ Result.IntReal = HandleIntToIntCast(EltType, SrcType,
+ Result.IntReal,
+ Info.Ctx);
+ Result.IntImag = HandleIntToIntCast(EltType, SrcType,
+ Result.IntImag,
+ Info.Ctx);
return true;
}
- } else if (const ComplexType *CT = SubType->getAs<ComplexType>()) {
- if (!Visit(SubExpr))
- return false;
-
- QualType SrcType = CT->getElementType();
-
- if (Result.isComplexFloat()) {
- if (EltType->isRealFloatingType()) {
- Result.makeComplexFloat();
- Result.FloatReal = HandleFloatToFloatCast(EltType, SrcType,
- Result.FloatReal,
- Info.Ctx);
- Result.FloatImag = HandleFloatToFloatCast(EltType, SrcType,
- Result.FloatImag,
- Info.Ctx);
- return true;
- } else {
- Result.makeComplexInt();
- Result.IntReal = HandleFloatToIntCast(EltType, SrcType,
- Result.FloatReal,
- Info.Ctx);
- Result.IntImag = HandleFloatToIntCast(EltType, SrcType,
- Result.FloatImag,
- Info.Ctx);
- return true;
- }
- } else {
- assert(Result.isComplexInt() && "Invalid evaluate result.");
- if (EltType->isRealFloatingType()) {
- Result.makeComplexFloat();
- Result.FloatReal = HandleIntToFloatCast(EltType, SrcType,
- Result.IntReal,
- Info.Ctx);
- Result.FloatImag = HandleIntToFloatCast(EltType, SrcType,
- Result.IntImag,
- Info.Ctx);
- return true;
- } else {
- Result.makeComplexInt();
- Result.IntReal = HandleIntToIntCast(EltType, SrcType,
- Result.IntReal,
- Info.Ctx);
- Result.IntImag = HandleIntToIntCast(EltType, SrcType,
- Result.IntImag,
- Info.Ctx);
- return true;
- }
- }
}
-
- // FIXME: Handle more casts.
- return false;
}
- bool VisitBinaryOperator(const BinaryOperator *E);
- bool VisitChooseExpr(const ChooseExpr *E)
- { return Visit(E->getChosenSubExpr(Info.Ctx)); }
- bool VisitUnaryExtension(const UnaryOperator *E)
- { return Visit(E->getSubExpr()); }
- // FIXME Missing: unary +/-/~, binary div, ImplicitValueInitExpr,
- // conditional ?:, comma
-};
-} // end anonymous namespace
-
-static bool EvaluateComplex(const Expr *E, ComplexValue &Result,
- EvalInfo &Info) {
- assert(E->getType()->isAnyComplexType());
- return ComplexExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+ // FIXME: Handle more casts.
+ return false;
}
bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
@@ -2136,7 +2142,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
"Invalid operands to binary operator.");
switch (E->getOpcode()) {
default: return false;
- case BinaryOperator::Add:
+ case BO_Add:
if (Result.isComplexFloat()) {
Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),
APFloat::rmNearestTiesToEven);
@@ -2147,7 +2153,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Result.getComplexIntImag() += RHS.getComplexIntImag();
}
break;
- case BinaryOperator::Sub:
+ case BO_Sub:
if (Result.isComplexFloat()) {
Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),
APFloat::rmNearestTiesToEven);
@@ -2158,7 +2164,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Result.getComplexIntImag() -= RHS.getComplexIntImag();
}
break;
- case BinaryOperator::Mul:
+ case BO_Mul:
if (Result.isComplexFloat()) {
ComplexValue LHS = Result;
APFloat &LHS_r = LHS.getComplexFloatReal();
@@ -2321,6 +2327,8 @@ APSInt Expr::EvaluateAsInt(ASTContext &Ctx) const {
// the comma operator in C99 mode.
// 2: This expression is not an ICE, and is not a legal subexpression for one.
+namespace {
+
struct ICEDiag {
unsigned Val;
SourceLocation Loc;
@@ -2330,7 +2338,9 @@ struct ICEDiag {
ICEDiag() : Val(0) {}
};
-ICEDiag NoDiag() { return ICEDiag(); }
+}
+
+static ICEDiag NoDiag() { return ICEDiag(); }
static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) {
Expr::EvalResult EVResult;
@@ -2380,7 +2390,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::DependentScopeDeclRefExprClass:
case Expr::CXXConstructExprClass:
case Expr::CXXBindTemporaryExprClass:
- case Expr::CXXBindReferenceExprClass:
case Expr::CXXExprWithTemporariesClass:
case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXUnresolvedConstructExprClass:
@@ -2476,23 +2485,21 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::UnaryOperatorClass: {
const UnaryOperator *Exp = cast<UnaryOperator>(E);
switch (Exp->getOpcode()) {
- case UnaryOperator::PostInc:
- case UnaryOperator::PostDec:
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec:
- case UnaryOperator::AddrOf:
- case UnaryOperator::Deref:
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec:
+ case UO_AddrOf:
+ case UO_Deref:
return ICEDiag(2, E->getLocStart());
- case UnaryOperator::Extension:
- case UnaryOperator::LNot:
- case UnaryOperator::Plus:
- case UnaryOperator::Minus:
- case UnaryOperator::Not:
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
+ case UO_Extension:
+ case UO_LNot:
+ case UO_Plus:
+ case UO_Minus:
+ case UO_Not:
+ case UO_Real:
+ case UO_Imag:
return CheckICE(Exp->getSubExpr(), Ctx);
- case UnaryOperator::OffsetOf:
- break;
}
// OffsetOf falls through here.
@@ -2515,42 +2522,42 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::BinaryOperatorClass: {
const BinaryOperator *Exp = cast<BinaryOperator>(E);
switch (Exp->getOpcode()) {
- case BinaryOperator::PtrMemD:
- case BinaryOperator::PtrMemI:
- case BinaryOperator::Assign:
- case BinaryOperator::MulAssign:
- case BinaryOperator::DivAssign:
- case BinaryOperator::RemAssign:
- case BinaryOperator::AddAssign:
- case BinaryOperator::SubAssign:
- case BinaryOperator::ShlAssign:
- case BinaryOperator::ShrAssign:
- case BinaryOperator::AndAssign:
- case BinaryOperator::XorAssign:
- case BinaryOperator::OrAssign:
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_Assign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
return ICEDiag(2, E->getLocStart());
- case BinaryOperator::Mul:
- case BinaryOperator::Div:
- case BinaryOperator::Rem:
- case BinaryOperator::Add:
- case BinaryOperator::Sub:
- case BinaryOperator::Shl:
- case BinaryOperator::Shr:
- case BinaryOperator::LT:
- case BinaryOperator::GT:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
- case BinaryOperator::EQ:
- case BinaryOperator::NE:
- case BinaryOperator::And:
- case BinaryOperator::Xor:
- case BinaryOperator::Or:
- case BinaryOperator::Comma: {
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ case BO_Comma: {
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
- if (Exp->getOpcode() == BinaryOperator::Div ||
- Exp->getOpcode() == BinaryOperator::Rem) {
+ if (Exp->getOpcode() == BO_Div ||
+ Exp->getOpcode() == BO_Rem) {
// Evaluate gives an error for undefined Div/Rem, so make sure
// we don't evaluate one.
if (LHSResult.Val != 2 && RHSResult.Val != 2) {
@@ -2564,7 +2571,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
}
}
}
- if (Exp->getOpcode() == BinaryOperator::Comma) {
+ if (Exp->getOpcode() == BO_Comma) {
if (Ctx.getLangOptions().C99) {
// C99 6.6p3 introduces a strange edge case: comma can be in an ICE
// if it isn't evaluated.
@@ -2579,15 +2586,15 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
return LHSResult;
return RHSResult;
}
- case BinaryOperator::LAnd:
- case BinaryOperator::LOr: {
+ case BO_LAnd:
+ case BO_LOr: {
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
if (LHSResult.Val == 0 && RHSResult.Val == 1) {
// Rare case where the RHS has a comma "side-effect"; we need
// to actually check the condition to see whether the side
// with the comma is evaluated.
- if ((Exp->getOpcode() == BinaryOperator::LAnd) !=
+ if ((Exp->getOpcode() == BO_LAnd) !=
(Exp->getLHS()->EvaluateAsInt(Ctx) == 0))
return RHSResult;
return NoDiag();
diff --git a/lib/AST/FullExpr.cpp b/lib/AST/FullExpr.cpp
index f47284f3d060..93ee8d136000 100644
--- a/lib/AST/FullExpr.cpp
+++ b/lib/AST/FullExpr.cpp
@@ -43,16 +43,3 @@ FullExpr FullExpr::Create(ASTContext &Context, Expr *SubExpr,
return E;
}
-void FullExpr::Destroy(ASTContext &Context) {
- if (Expr *E = SubExpr.dyn_cast<Expr *>()) {
- E->Destroy(Context);
- return;
- }
-
- ExprAndTemporaries *ET = SubExpr.get<ExprAndTemporaries *>();
- for (ExprAndTemporaries::temps_iterator i = ET->temps_begin(),
- e = ET->temps_end(); i != e; ++i)
- (*i)->Destroy(Context);
-
- Context.Deallocate(ET);
-}
diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp
new file mode 100644
index 000000000000..c3fa4666537b
--- /dev/null
+++ b/lib/AST/ItaniumCXXABI.cpp
@@ -0,0 +1,52 @@
+//===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ AST support targetting the Itanium C++ ABI, which is
+// documented at:
+// http://www.codesourcery.com/public/cxx-abi/abi.html
+// http://www.codesourcery.com/public/cxx-abi/abi-eh.html
+//
+// It also supports the closely-related ARM C++ ABI, documented at:
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXXABI.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+
+using namespace clang;
+
+namespace {
+class ItaniumCXXABI : public CXXABI {
+protected:
+ ASTContext &Context;
+public:
+ ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
+
+ unsigned getMemberPointerSize(const MemberPointerType *MPT) const {
+ QualType Pointee = MPT->getPointeeType();
+ if (Pointee->isFunctionType()) return 2;
+ return 1;
+ }
+};
+
+class ARMCXXABI : public ItaniumCXXABI {
+public:
+ ARMCXXABI(ASTContext &Ctx) : ItaniumCXXABI(Ctx) { }
+};
+}
+
+CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) {
+ return new ItaniumCXXABI(Ctx);
+}
+
+CXXABI *clang::CreateARMCXXABI(ASTContext &Ctx) {
+ return new ARMCXXABI(Ctx);
+}
diff --git a/lib/AST/Makefile b/lib/AST/Makefile
index 7a1672b81728..65383c5552d4 100644
--- a/lib/AST/Makefile
+++ b/lib/AST/Makefile
@@ -13,7 +13,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangAST
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp
new file mode 100644
index 000000000000..87b77673925f
--- /dev/null
+++ b/lib/AST/MicrosoftCXXABI.cpp
@@ -0,0 +1,48 @@
+//===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ AST support targetting the Microsoft Visual C++
+// ABI.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXXABI.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/DeclCXX.h"
+
+using namespace clang;
+
+namespace {
+class MicrosoftCXXABI : public CXXABI {
+ ASTContext &Context;
+public:
+ MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
+
+ unsigned getMemberPointerSize(const MemberPointerType *MPT) const;
+};
+}
+
+unsigned MicrosoftCXXABI::getMemberPointerSize(const MemberPointerType *MPT) const {
+ QualType Pointee = MPT->getPointeeType();
+ CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+ if (RD->getNumVBases() > 0) {
+ if (Pointee->isFunctionType())
+ return 3;
+ else
+ return 2;
+ } else if (RD->getNumBases() > 1 && Pointee->isFunctionType())
+ return 2;
+ return 1;
+}
+
+CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
+ return new MicrosoftCXXABI(Ctx);
+}
+
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index d6594cdfd02f..212def8565ea 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -176,11 +176,6 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS,
OS << "::";
}
-void NestedNameSpecifier::Destroy(ASTContext &Context) {
- this->~NestedNameSpecifier();
- Context.Deallocate((void *)this);
-}
-
void NestedNameSpecifier::dump(const LangOptions &LO) {
print(llvm::errs(), PrintingPolicy(LO));
}
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index 48251d52fd2a..5fe873acf7ac 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -73,7 +73,7 @@ bool ParentMap::isConsumedExpr(Expr* E) const {
BinaryOperator *BE = cast<BinaryOperator>(P);
// If it is a comma, only the right side is consumed.
// If it isn't a comma, both sides are consumed.
- return BE->getOpcode()!=BinaryOperator::Comma ||DirectChild==BE->getRHS();
+ return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
}
case Stmt::ForStmtClass:
return DirectChild == cast<ForStmt>(P)->getCond();
diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp
index 262c4597f846..4d9c51633626 100644
--- a/lib/AST/RecordLayout.cpp
+++ b/lib/AST/RecordLayout.cpp
@@ -19,8 +19,10 @@ using namespace clang;
void ASTRecordLayout::Destroy(ASTContext &Ctx) {
if (FieldOffsets)
Ctx.Deallocate(FieldOffsets);
- if (CXXInfo)
+ if (CXXInfo) {
Ctx.Deallocate(CXXInfo);
+ CXXInfo->~CXXRecordLayoutInfo();
+ }
this->~ASTRecordLayout();
Ctx.Deallocate(this);
}
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 88d71ce04287..13fae299d877 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -73,22 +73,11 @@ class EmptySubobjectMap {
/// member subobject that is empty.
void ComputeEmptySubobjectSizes();
- bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
- uint64_t Offset) const;
-
void AddSubobjectAtOffset(const CXXRecordDecl *RD, uint64_t Offset);
- bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
- uint64_t Offset);
void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
uint64_t Offset, bool PlacingEmptyBase);
- bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
- const CXXRecordDecl *Class,
- uint64_t Offset) const;
- bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
- uint64_t Offset) const;
-
void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
const CXXRecordDecl *Class,
uint64_t Offset);
@@ -100,6 +89,19 @@ class EmptySubobjectMap {
return Offset <= MaxEmptyClassOffset;
}
+protected:
+ bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
+ uint64_t Offset) const;
+
+ bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
+ uint64_t Offset);
+
+ bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ uint64_t Offset) const;
+ bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
+ uint64_t Offset) const;
+
public:
/// This holds the size of the largest empty subobject (either a base
/// or a member). Will be zero if the record being built doesn't contain
@@ -513,6 +515,7 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD,
}
class RecordLayoutBuilder {
+protected:
// FIXME: Remove this and make the appropriate fields public.
friend class clang::ASTContext;
@@ -623,12 +626,14 @@ class RecordLayoutBuilder {
void SelectPrimaryVBase(const CXXRecordDecl *RD);
+ virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
+
/// IdentifyPrimaryBases - Identify all virtual base classes, direct or
/// indirect, that are primary base classes for some other direct or indirect
/// base class.
void IdentifyPrimaryBases(const CXXRecordDecl *RD);
- bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
+ virtual bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
/// LayoutNonVirtualBases - Determines the primary base class (if any) and
/// lays it out. Will then proceed to lay out all non-virtual base clasess.
@@ -638,7 +643,7 @@ class RecordLayoutBuilder {
void LayoutNonVirtualBase(const BaseSubobjectInfo *Base);
void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
- uint64_t Offset);
+ uint64_t Offset);
/// LayoutVirtualBases - Lays out all the virtual bases.
void LayoutVirtualBases(const CXXRecordDecl *RD,
@@ -664,6 +669,8 @@ class RecordLayoutBuilder {
void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
public:
static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
+
+ virtual ~RecordLayoutBuilder() { }
};
} // end anonymous namespace
@@ -734,6 +741,11 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
}
}
+uint64_t
+RecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
+ return Context.Target.getPointerWidth(0);
+}
+
/// DeterminePrimaryBase - Determine the primary base of the given class.
void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
// If the class isn't dynamic, it won't have a primary base.
@@ -794,7 +806,7 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
// Update the size.
- Size += Context.Target.getPointerWidth(0);
+ Size += GetVirtualPointersSize(RD);
DataSize = Size;
// Update the alignment.
@@ -1123,8 +1135,8 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
MaxFieldAlignment = MFAA->getAlignment();
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- UpdateAlignment(AA->getMaxAlignment());
+ if (unsigned MaxAlign = D->getMaxAlignment())
+ UpdateAlignment(MaxAlign);
}
}
@@ -1287,8 +1299,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
FieldAlign = 1;
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
+ FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
@@ -1357,8 +1368,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
if (FieldPacked)
FieldAlign = 8;
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
+ FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
@@ -1453,6 +1463,37 @@ RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
return 0;
}
+// This class implements layout specific to the Microsoft ABI.
+class MSRecordLayoutBuilder: public RecordLayoutBuilder {
+public:
+ MSRecordLayoutBuilder(ASTContext& Ctx, EmptySubobjectMap *EmptySubobjects):
+ RecordLayoutBuilder(Ctx, EmptySubobjects) {}
+
+ virtual bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
+ virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
+};
+
+bool MSRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
+ // FIXME: Audit the corners
+ if (!RD->isDynamicClass())
+ return false;
+ const ASTRecordLayout &BaseInfo = Context.getASTRecordLayout(RD);
+ // In the Microsoft ABI, classes can have one or two vtable pointers.
+ if (BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0) ||
+ BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0) * 2)
+ return true;
+ return false;
+}
+
+uint64_t
+MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
+ // We should reserve space for two pointers if the class has both
+ // virtual functions and virtual bases.
+ if (RD->isPolymorphic() && RD->getNumVBases() > 0)
+ return 2 * Context.Target.getPointerWidth(0);
+ return Context.Target.getPointerWidth(0);
+}
+
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
@@ -1471,8 +1512,16 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
EmptySubobjectMap EmptySubobjects(*this, RD);
- RecordLayoutBuilder Builder(*this, &EmptySubobjects);
- Builder.Layout(RD);
+ // When compiling for Microsoft, use the special MS builder.
+ llvm::OwningPtr<RecordLayoutBuilder> Builder;
+ switch (Target.getCXXABI()) {
+ default:
+ Builder.reset(new RecordLayoutBuilder(*this, &EmptySubobjects));
+ break;
+ case CXXABI_Microsoft:
+ Builder.reset(new MSRecordLayoutBuilder(*this, &EmptySubobjects));
+ }
+ Builder->Layout(RD);
// FIXME: This is not always correct. See the part about bitfields at
// http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
@@ -1481,20 +1530,20 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
// FIXME: This should be done in FinalizeLayout.
uint64_t DataSize =
- IsPODForThePurposeOfLayout ? Builder.Size : Builder.DataSize;
+ IsPODForThePurposeOfLayout ? Builder->Size : Builder->DataSize;
uint64_t NonVirtualSize =
- IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
+ IsPODForThePurposeOfLayout ? DataSize : Builder->NonVirtualSize;
NewEntry =
- new (*this) ASTRecordLayout(*this, Builder.Size, Builder.Alignment,
- DataSize, Builder.FieldOffsets.data(),
- Builder.FieldOffsets.size(),
+ new (*this) ASTRecordLayout(*this, Builder->Size, Builder->Alignment,
+ DataSize, Builder->FieldOffsets.data(),
+ Builder->FieldOffsets.size(),
NonVirtualSize,
- Builder.NonVirtualAlignment,
+ Builder->NonVirtualAlignment,
EmptySubobjects.SizeOfLargestEmptySubobject,
- Builder.PrimaryBase,
- Builder.PrimaryBaseIsVirtual,
- Builder.Bases, Builder.VBases);
+ Builder->PrimaryBase,
+ Builder->PrimaryBaseIsVirtual,
+ Builder->Bases, Builder->VBases);
} else {
RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
Builder.Layout(D);
@@ -1630,7 +1679,7 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel,
- Field->getNameAsCString(),
+ Field->getName().data(),
/*IncludeVirtualBases=*/true);
continue;
}
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 6dbe8f4d18c1..fc8898173f3e 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -119,7 +119,7 @@ bool Stmt::hasImplicitControlFlow() const {
case Stmt::BinaryOperatorClass: {
const BinaryOperator* B = cast<BinaryOperator>(this);
- if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma)
+ if (B->isLogicalOp() || B->getOpcode() == BO_Comma)
return true;
else
return false;
@@ -215,8 +215,9 @@ int AsmStmt::getNamedOperand(llvm::StringRef SymbolicName) const {
/// true, otherwise return false.
unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
ASTContext &C, unsigned &DiagOffs) const {
- const char *StrStart = getAsmString()->getStrData();
- const char *StrEnd = StrStart + getAsmString()->getByteLength();
+ llvm::StringRef Str = getAsmString()->getString();
+ const char *StrStart = Str.begin();
+ const char *StrEnd = Str.end();
const char *CurPtr = StrStart;
// "Simple" inline asms have no constraints or operands, just convert the asm
@@ -451,6 +452,15 @@ CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc,
return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers, numHandlers);
}
+CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty,
+ unsigned numHandlers) {
+ std::size_t Size = sizeof(CXXTryStmt);
+ Size += ((numHandlers + 1) * sizeof(Stmt));
+
+ void *Mem = C.Allocate(Size, llvm::alignof<CXXTryStmt>());
+ return new (Mem) CXXTryStmt(Empty, numHandlers);
+}
+
CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
Stmt **handlers, unsigned numHandlers)
: Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) {
@@ -459,46 +469,6 @@ CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
std::copy(handlers, handlers + NumHandlers, Stmts + 1);
}
-//===----------------------------------------------------------------------===//
-// AST Destruction.
-//===----------------------------------------------------------------------===//
-
-void Stmt::DestroyChildren(ASTContext &C) {
- for (child_iterator I = child_begin(), E = child_end(); I !=E; )
- if (Stmt* Child = *I++) Child->Destroy(C);
-}
-
-static void BranchDestroy(ASTContext &C, Stmt *S, Stmt **SubExprs,
- unsigned NumExprs) {
- // We do not use child_iterator here because that will include
- // the expressions referenced by the condition variable.
- for (Stmt **I = SubExprs, **E = SubExprs + NumExprs; I != E; ++I)
- if (Stmt *Child = *I) Child->Destroy(C);
-
- S->~Stmt();
- C.Deallocate((void *) S);
-}
-
-void Stmt::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- this->~Stmt();
- C.Deallocate((void *)this);
-}
-
-void CXXCatchStmt::DoDestroy(ASTContext& C) {
- if (ExceptionDecl)
- ExceptionDecl->Destroy(C);
- Stmt::DoDestroy(C);
-}
-
-void DeclStmt::DoDestroy(ASTContext &C) {
- // Don't use StmtIterator to iterate over the Decls, as that can recurse
- // into VLA size expressions (which are owned by the VLA). Further, Decls
- // are owned by the DeclContext, and will be destroyed with them.
- if (DG.isDeclGroup())
- DG.getDeclGroup().Destroy(C);
-}
-
IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
Stmt *then, SourceLocation EL, Stmt *elsev)
: Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL)
@@ -528,10 +498,6 @@ void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
V->getSourceRange().getEnd());
}
-void IfStmt::DoDestroy(ASTContext &C) {
- BranchDestroy(C, this, SubExprs, END_EXPR);
-}
-
ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
SourceLocation RP)
@@ -563,10 +529,6 @@ void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
V->getSourceRange().getEnd());
}
-void ForStmt::DoDestroy(ASTContext &C) {
- BranchDestroy(C, this, SubExprs, END_EXPR);
-}
-
SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond)
: Stmt(SwitchStmtClass), FirstCase(0)
{
@@ -594,20 +556,6 @@ void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
V->getSourceRange().getEnd());
}
-void SwitchStmt::DoDestroy(ASTContext &C) {
- // Destroy the SwitchCase statements in this switch. In the normal
- // case, this loop will merely decrement the reference counts from
- // the Retain() calls in addSwitchCase();
- SwitchCase *SC = FirstCase;
- while (SC) {
- SwitchCase *Next = SC->getNextSwitchCase();
- SC->Destroy(C);
- SC = Next;
- }
-
- BranchDestroy(C, this, SubExprs, END_EXPR);
-}
-
WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
SourceLocation WL)
: Stmt(WhileStmtClass)
@@ -637,22 +585,6 @@ void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
V->getSourceRange().getEnd());
}
-void WhileStmt::DoDestroy(ASTContext &C) {
- BranchDestroy(C, this, SubExprs, END_EXPR);
-}
-
-void AsmStmt::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
-
- C.Deallocate(Names);
- C.Deallocate(Constraints);
- C.Deallocate(Exprs);
- C.Deallocate(Clobbers);
-
- this->~AsmStmt();
- C.Deallocate((void *)this);
-}
-
//===----------------------------------------------------------------------===//
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index b388a3b18ffa..5c236a45a690 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -65,6 +65,13 @@ namespace {
OS << '\n';
DumpSubTree(*CI++);
}
+ if (const ConditionalOperator *CO =
+ dyn_cast<ConditionalOperator>(S)) {
+ if (CO->getSAVE()) {
+ OS << '\n';
+ DumpSubTree(CO->getSAVE());
+ }
+ }
}
}
OS << ')';
@@ -225,7 +232,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
OS << "\"";
// Emit storage class for vardecls.
if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
- if (V->getStorageClass() != VarDecl::None)
+ if (V->getStorageClass() != SC_None)
OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass())
<< " ";
}
@@ -308,13 +315,13 @@ void StmtDumper::VisitExpr(Expr *Node) {
}
static void DumpBasePath(llvm::raw_ostream &OS, CastExpr *Node) {
- if (Node->getBasePath().empty())
+ if (Node->path_empty())
return;
OS << " (";
bool First = true;
- for (CXXBaseSpecifierArray::iterator I = Node->getBasePath().begin(),
- E = Node->getBasePath().end(); I != E; ++I) {
+ for (CastExpr::path_iterator
+ I = Node->path_begin(), E = Node->path_end(); I != E; ++I) {
const CXXBaseSpecifier *Base = *I;
if (!First)
OS << " -> ";
@@ -340,8 +347,16 @@ void StmtDumper::VisitCastExpr(CastExpr *Node) {
void StmtDumper::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
VisitCastExpr(Node);
- if (Node->isLvalueCast())
+ switch (Node->getValueKind()) {
+ case VK_LValue:
OS << " lvalue";
+ break;
+ case VK_XValue:
+ OS << " xvalue";
+ break;
+ case VK_RValue:
+ break;
+ }
}
void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
@@ -421,8 +436,7 @@ void StmtDumper::VisitStringLiteral(StringLiteral *Str) {
if (Str->isWide())
OS << "L";
OS << '"';
- OS.write_escaped(llvm::StringRef(Str->getStrData(),
- Str->getByteLength()));
+ OS.write_escaped(Str->getString());
OS << '"';
}
@@ -511,6 +525,8 @@ void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) {
DumpType(Ctor->getType());
if (Node->isElidable())
OS << " elidable";
+ if (Node->requiresZeroInitialization())
+ OS << " zeroing";
}
void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
@@ -623,9 +639,13 @@ void StmtDumper::VisitObjCSuperExpr(ObjCSuperExpr *Node) {
/// specified node and a few nodes underneath it, but not the whole subtree.
/// This is useful in a debugger.
void Stmt::dump(SourceManager &SM) const {
- StmtDumper P(&SM, llvm::errs(), 4);
+ dump(llvm::errs(), SM);
+}
+
+void Stmt::dump(llvm::raw_ostream &OS, SourceManager &SM) const {
+ StmtDumper P(&SM, OS, 4);
P.DumpSubTree(const_cast<Stmt*>(this));
- llvm::errs() << "\n";
+ OS << "\n";
}
/// dump - This does a local dump of the specified AST fragment. It dumps the
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 7043c3551628..5236a6672622 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -77,16 +77,21 @@ namespace {
return OS;
}
- bool PrintOffsetOfDesignator(Expr *E);
- void VisitUnaryOffsetOf(UnaryOperator *Node);
-
void Visit(Stmt* S) {
if (Helper && Helper->handledStmt(S,OS))
return;
else StmtVisitor<StmtPrinter>::Visit(S);
}
+
+ void VisitStmt(Stmt *Node) ATTRIBUTE_UNUSED {
+ Indent() << "<<unknown stmt type>>\n";
+ }
+ void VisitExpr(Expr *Node) ATTRIBUTE_UNUSED {
+ OS << "<<unknown expr type>>";
+ }
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
- void VisitStmt(Stmt *Node);
+#define ABSTRACT_STMT(CLASS)
#define STMT(CLASS, PARENT) \
void Visit##CLASS(CLASS *Node);
#include "clang/AST/StmtNodes.inc"
@@ -97,10 +102,6 @@ namespace {
// Stmt printing methods.
//===----------------------------------------------------------------------===//
-void StmtPrinter::VisitStmt(Stmt *Node) {
- Indent() << "<<unknown stmt type>>\n";
-}
-
/// PrintRawCompoundStmt - Print a compound stmt without indenting the {, and
/// with no newline after the }.
void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) {
@@ -465,15 +466,11 @@ void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) {
// Expr printing methods.
//===----------------------------------------------------------------------===//
-void StmtPrinter::VisitExpr(Expr *Node) {
- OS << "<<unknown expr type>>";
-}
-
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
Qualifier->print(OS, Policy);
- OS << Node->getDecl();
- if (Node->hasExplicitTemplateArgumentList())
+ OS << Node->getNameInfo();
+ if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
Node->getNumTemplateArgs(),
@@ -483,7 +480,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
void StmtPrinter::VisitDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *Node) {
Node->getQualifier()->print(OS, Policy);
- OS << Node->getDeclName().getAsString();
+ OS << Node->getNameInfo();
if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
@@ -494,7 +491,7 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr(
void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
if (Node->getQualifier())
Node->getQualifier()->print(OS, Policy);
- OS << Node->getName().getAsString();
+ OS << Node->getNameInfo();
if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
@@ -515,7 +512,7 @@ void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
PrintExpr(Node->getBase());
OS << ".";
}
- OS << Node->getProperty()->getNameAsCString();
+ OS << Node->getProperty()->getName();
}
void StmtPrinter::VisitObjCImplicitSetterGetterRefExpr(
@@ -624,8 +621,10 @@ void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
OS << '"';
// FIXME: this doesn't print wstrings right.
- for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) {
- unsigned char Char = Str->getStrData()[i];
+ llvm::StringRef StrData = Str->getString();
+ for (llvm::StringRef::iterator I = StrData.begin(), E = StrData.end();
+ I != E; ++I) {
+ unsigned char Char = *I;
switch (Char) {
default:
@@ -661,13 +660,13 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
// it might be concatenated incorrectly like '+'.
switch (Node->getOpcode()) {
default: break;
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
- case UnaryOperator::Extension:
+ case UO_Real:
+ case UO_Imag:
+ case UO_Extension:
OS << ' ';
break;
- case UnaryOperator::Plus:
- case UnaryOperator::Minus:
+ case UO_Plus:
+ case UO_Minus:
if (isa<UnaryOperator>(Node->getSubExpr()))
OS << ' ';
break;
@@ -679,31 +678,6 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
}
-bool StmtPrinter::PrintOffsetOfDesignator(Expr *E) {
- if (isa<UnaryOperator>(E)) {
- // Base case, print the type and comma.
- OS << E->getType().getAsString(Policy) << ", ";
- return true;
- } else if (ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
- PrintOffsetOfDesignator(ASE->getLHS());
- OS << "[";
- PrintExpr(ASE->getRHS());
- OS << "]";
- return false;
- } else {
- MemberExpr *ME = cast<MemberExpr>(E);
- bool IsFirst = PrintOffsetOfDesignator(ME->getBase());
- OS << (IsFirst ? "" : ".") << ME->getMemberDecl();
- return false;
- }
-}
-
-void StmtPrinter::VisitUnaryOffsetOf(UnaryOperator *Node) {
- OS << "__builtin_offsetof(";
- PrintOffsetOfDesignator(Node->getSubExpr());
- OS << ")";
-}
-
void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
OS << "__builtin_offsetof(";
OS << Node->getTypeSourceInfo()->getType().getAsString(Policy) << ", ";
@@ -777,9 +751,9 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
Qualifier->print(OS, Policy);
- OS << Node->getMemberDecl();
+ OS << Node->getMemberNameInfo();
- if (Node->hasExplicitTemplateArgumentList())
+ if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
Node->getNumTemplateArgs(),
@@ -795,12 +769,6 @@ void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
OS << ".";
OS << Node->getAccessor().getName();
}
-void StmtPrinter::VisitCastExpr(CastExpr *) {
- assert(0 && "CastExpr is an abstract class");
-}
-void StmtPrinter::VisitExplicitCastExpr(ExplicitCastExpr *) {
- assert(0 && "ExplicitCastExpr is an abstract class");
-}
void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
OS << "(" << Node->getType().getAsString(Policy) << ")";
PrintExpr(Node->getSubExpr());
@@ -1069,10 +1037,6 @@ void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
PrintExpr(Node->getSubExpr());
}
-void StmtPrinter::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *Node) {
- PrintExpr(Node->getSubExpr());
-}
-
void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
OS << Node->getType().getAsString(Policy);
OS << "(";
@@ -1201,7 +1165,7 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr(
// FIXME: Track use of "template" keyword explicitly?
OS << "template ";
- OS << Node->getMember().getAsString();
+ OS << Node->getMemberNameInfo();
if (Node->hasExplicitTemplateArgs()) {
OS << TemplateSpecializationType::PrintTemplateArgumentList(
@@ -1221,7 +1185,7 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
// FIXME: this might originally have been written with 'template'
- OS << Node->getMemberName().getAsString();
+ OS << Node->getMemberNameInfo();
if (Node->hasExplicitTemplateArgs()) {
OS << TemplateSpecializationType::PrintTemplateArgumentList(
@@ -1368,7 +1332,7 @@ void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context,
}
if (Policy.Dump && &Context) {
- dump(Context.getSourceManager());
+ dump(OS, Context.getSourceManager());
return;
}
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index cff86a4e1cec..78a336d2bfbe 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -325,7 +325,7 @@ void StmtProfiler::VisitCastExpr(CastExpr *S) {
void StmtProfiler::VisitImplicitCastExpr(ImplicitCastExpr *S) {
VisitCastExpr(S);
- ID.AddBoolean(S->isLvalueCast());
+ ID.AddInteger(S->getValueKind());
}
void StmtProfiler::VisitExplicitCastExpr(ExplicitCastExpr *S) {
@@ -436,8 +436,8 @@ void StmtProfiler::VisitBlockDeclRefExpr(BlockDeclRefExpr *S) {
}
static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
- UnaryOperator::Opcode &UnaryOp,
- BinaryOperator::Opcode &BinaryOp) {
+ UnaryOperatorKind &UnaryOp,
+ BinaryOperatorKind &BinaryOp) {
switch (S->getOperator()) {
case OO_None:
case OO_New:
@@ -453,165 +453,165 @@ static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
case OO_Plus:
if (S->getNumArgs() == 1) {
- UnaryOp = UnaryOperator::Plus;
+ UnaryOp = UO_Plus;
return Stmt::UnaryOperatorClass;
}
- BinaryOp = BinaryOperator::Add;
+ BinaryOp = BO_Add;
return Stmt::BinaryOperatorClass;
case OO_Minus:
if (S->getNumArgs() == 1) {
- UnaryOp = UnaryOperator::Minus;
+ UnaryOp = UO_Minus;
return Stmt::UnaryOperatorClass;
}
- BinaryOp = BinaryOperator::Sub;
+ BinaryOp = BO_Sub;
return Stmt::BinaryOperatorClass;
case OO_Star:
if (S->getNumArgs() == 1) {
- UnaryOp = UnaryOperator::Minus;
+ UnaryOp = UO_Minus;
return Stmt::UnaryOperatorClass;
}
- BinaryOp = BinaryOperator::Sub;
+ BinaryOp = BO_Sub;
return Stmt::BinaryOperatorClass;
case OO_Slash:
- BinaryOp = BinaryOperator::Div;
+ BinaryOp = BO_Div;
return Stmt::BinaryOperatorClass;
case OO_Percent:
- BinaryOp = BinaryOperator::Rem;
+ BinaryOp = BO_Rem;
return Stmt::BinaryOperatorClass;
case OO_Caret:
- BinaryOp = BinaryOperator::Xor;
+ BinaryOp = BO_Xor;
return Stmt::BinaryOperatorClass;
case OO_Amp:
if (S->getNumArgs() == 1) {
- UnaryOp = UnaryOperator::AddrOf;
+ UnaryOp = UO_AddrOf;
return Stmt::UnaryOperatorClass;
}
- BinaryOp = BinaryOperator::And;
+ BinaryOp = BO_And;
return Stmt::BinaryOperatorClass;
case OO_Pipe:
- BinaryOp = BinaryOperator::Or;
+ BinaryOp = BO_Or;
return Stmt::BinaryOperatorClass;
case OO_Tilde:
- UnaryOp = UnaryOperator::Not;
+ UnaryOp = UO_Not;
return Stmt::UnaryOperatorClass;
case OO_Exclaim:
- UnaryOp = UnaryOperator::LNot;
+ UnaryOp = UO_LNot;
return Stmt::UnaryOperatorClass;
case OO_Equal:
- BinaryOp = BinaryOperator::Assign;
+ BinaryOp = BO_Assign;
return Stmt::BinaryOperatorClass;
case OO_Less:
- BinaryOp = BinaryOperator::LT;
+ BinaryOp = BO_LT;
return Stmt::BinaryOperatorClass;
case OO_Greater:
- BinaryOp = BinaryOperator::GT;
+ BinaryOp = BO_GT;
return Stmt::BinaryOperatorClass;
case OO_PlusEqual:
- BinaryOp = BinaryOperator::AddAssign;
+ BinaryOp = BO_AddAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_MinusEqual:
- BinaryOp = BinaryOperator::SubAssign;
+ BinaryOp = BO_SubAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_StarEqual:
- BinaryOp = BinaryOperator::MulAssign;
+ BinaryOp = BO_MulAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_SlashEqual:
- BinaryOp = BinaryOperator::DivAssign;
+ BinaryOp = BO_DivAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_PercentEqual:
- BinaryOp = BinaryOperator::RemAssign;
+ BinaryOp = BO_RemAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_CaretEqual:
- BinaryOp = BinaryOperator::XorAssign;
+ BinaryOp = BO_XorAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_AmpEqual:
- BinaryOp = BinaryOperator::AndAssign;
+ BinaryOp = BO_AndAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_PipeEqual:
- BinaryOp = BinaryOperator::OrAssign;
+ BinaryOp = BO_OrAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_LessLess:
- BinaryOp = BinaryOperator::Shl;
+ BinaryOp = BO_Shl;
return Stmt::BinaryOperatorClass;
case OO_GreaterGreater:
- BinaryOp = BinaryOperator::Shr;
+ BinaryOp = BO_Shr;
return Stmt::BinaryOperatorClass;
case OO_LessLessEqual:
- BinaryOp = BinaryOperator::ShlAssign;
+ BinaryOp = BO_ShlAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_GreaterGreaterEqual:
- BinaryOp = BinaryOperator::ShrAssign;
+ BinaryOp = BO_ShrAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_EqualEqual:
- BinaryOp = BinaryOperator::EQ;
+ BinaryOp = BO_EQ;
return Stmt::BinaryOperatorClass;
case OO_ExclaimEqual:
- BinaryOp = BinaryOperator::NE;
+ BinaryOp = BO_NE;
return Stmt::BinaryOperatorClass;
case OO_LessEqual:
- BinaryOp = BinaryOperator::LE;
+ BinaryOp = BO_LE;
return Stmt::BinaryOperatorClass;
case OO_GreaterEqual:
- BinaryOp = BinaryOperator::GE;
+ BinaryOp = BO_GE;
return Stmt::BinaryOperatorClass;
case OO_AmpAmp:
- BinaryOp = BinaryOperator::LAnd;
+ BinaryOp = BO_LAnd;
return Stmt::BinaryOperatorClass;
case OO_PipePipe:
- BinaryOp = BinaryOperator::LOr;
+ BinaryOp = BO_LOr;
return Stmt::BinaryOperatorClass;
case OO_PlusPlus:
- UnaryOp = S->getNumArgs() == 1? UnaryOperator::PreInc
- : UnaryOperator::PostInc;
+ UnaryOp = S->getNumArgs() == 1? UO_PreInc
+ : UO_PostInc;
return Stmt::UnaryOperatorClass;
case OO_MinusMinus:
- UnaryOp = S->getNumArgs() == 1? UnaryOperator::PreDec
- : UnaryOperator::PostDec;
+ UnaryOp = S->getNumArgs() == 1? UO_PreDec
+ : UO_PostDec;
return Stmt::UnaryOperatorClass;
case OO_Comma:
- BinaryOp = BinaryOperator::Comma;
+ BinaryOp = BO_Comma;
return Stmt::BinaryOperatorClass;
case OO_ArrowStar:
- BinaryOp = BinaryOperator::PtrMemI;
+ BinaryOp = BO_PtrMemI;
return Stmt::BinaryOperatorClass;
case OO_Subscript:
@@ -626,8 +626,8 @@ void StmtProfiler::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
if (S->isTypeDependent()) {
// Type-dependent operator calls are profiled like their underlying
// syntactic operator.
- UnaryOperator::Opcode UnaryOp = UnaryOperator::Extension;
- BinaryOperator::Opcode BinaryOp = BinaryOperator::Comma;
+ UnaryOperatorKind UnaryOp = UO_Extension;
+ BinaryOperatorKind BinaryOp = BO_Comma;
Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp);
ID.AddInteger(SC);
@@ -706,10 +706,6 @@ void StmtProfiler::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *S) {
const_cast<CXXDestructorDecl *>(S->getTemporary()->getDestructor()));
}
-void StmtProfiler::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *S) {
- VisitExpr(S);
-}
-
void StmtProfiler::VisitCXXConstructExpr(CXXConstructExpr *S) {
VisitExpr(S);
VisitDecl(S->getConstructor());
@@ -757,14 +753,19 @@ void StmtProfiler::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *S) {
VisitType(S->getDestroyedType());
}
-void
-StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
+void StmtProfiler::VisitOverloadExpr(OverloadExpr *S) {
VisitExpr(S);
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getName());
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
- VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+ VisitTemplateArguments(S->getExplicitTemplateArgs().getTemplateArgs(),
+ S->getExplicitTemplateArgs().NumTemplateArgs);
+}
+
+void
+StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
+ VisitOverloadExpr(S);
}
void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 02e648879ad7..a3bf1459c283 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -125,19 +125,22 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
switch (Argument.getKind()) {
case TemplateArgument::Expression:
return getSourceExpression()->getSourceRange();
-
+
case TemplateArgument::Declaration:
return getSourceDeclExpression()->getSourceRange();
-
+
case TemplateArgument::Type:
- return getTypeSourceInfo()->getTypeLoc().getSourceRange();
-
+ if (TypeSourceInfo *TSI = getTypeSourceInfo())
+ return TSI->getTypeLoc().getSourceRange();
+ else
+ return SourceRange();
+
case TemplateArgument::Template:
if (getTemplateQualifierRange().isValid())
return SourceRange(getTemplateQualifierRange().getBegin(),
getTemplateNameLoc());
return SourceRange(getTemplateNameLoc());
-
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
@@ -152,7 +155,9 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
const TemplateArgument &Arg) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
- return DB;
+ // This is bad, but not as bad as crashing because of argument
+ // count mismatches.
+ return DB << "(null template argument)";
case TemplateArgument::Type:
return DB << Arg.getAsType();
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d7929304233f..ca10532e729e 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -21,6 +22,7 @@
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
using namespace clang;
bool QualType::isConstant(QualType T, ASTContext &Ctx) {
@@ -33,24 +35,32 @@ bool QualType::isConstant(QualType T, ASTContext &Ctx) {
return false;
}
-void Type::Destroy(ASTContext& C) {
- this->~Type();
- C.Deallocate(this);
-}
+Type::~Type() { }
+
+unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context,
+ QualType ElementType,
+ const llvm::APInt &NumElements) {
+ llvm::APSInt SizeExtended(NumElements, true);
+ unsigned SizeTypeBits = Context.getTypeSize(Context.getSizeType());
+ SizeExtended.extend(std::max(SizeTypeBits, SizeExtended.getBitWidth()) * 2);
-void VariableArrayType::Destroy(ASTContext& C) {
- if (SizeExpr)
- SizeExpr->Destroy(C);
- this->~VariableArrayType();
- C.Deallocate(this);
+ uint64_t ElementSize
+ = Context.getTypeSizeInChars(ElementType).getQuantity();
+ llvm::APSInt TotalSize(llvm::APInt(SizeExtended.getBitWidth(), ElementSize));
+ TotalSize *= SizeExtended;
+
+ return TotalSize.getActiveBits();
}
-void DependentSizedArrayType::Destroy(ASTContext& C) {
- // FIXME: Resource contention like in ConstantArrayWithExprType ?
- // May crash, depending on platform or a particular build.
- // SizeExpr->Destroy(C);
- this->~DependentSizedArrayType();
- C.Deallocate(this);
+unsigned ConstantArrayType::getMaxSizeBits(ASTContext &Context) {
+ unsigned Bits = Context.getTypeSize(Context.getSizeType());
+
+ // GCC appears to only allow 63 bits worth of address space when compiling
+ // for 64-bit, so we do the same.
+ if (Bits == 64)
+ --Bits;
+
+ return Bits;
}
void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
@@ -73,14 +83,6 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
SizeExpr->Profile(ID, Context, true);
}
-void DependentSizedExtVectorType::Destroy(ASTContext& C) {
- // FIXME: Deallocate size expression, once we're cloning properly.
-// if (SizeExpr)
-// SizeExpr->Destroy(C);
- this->~DependentSizedExtVectorType();
- C.Deallocate(this);
-}
-
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
@@ -192,13 +194,6 @@ bool Type::isVoidType() const {
return false;
}
-bool Type::isObjectType() const {
- if (isa<FunctionType>(CanonicalType) || isa<ReferenceType>(CanonicalType) ||
- isa<IncompleteArrayType>(CanonicalType) || isVoidType())
- return false;
- return true;
-}
-
bool Type::isDerivedType() const {
switch (CanonicalType->getTypeClass()) {
case Pointer:
@@ -348,11 +343,6 @@ const RecordType *Type::getAsUnionType() const {
return 0;
}
-void ObjCInterfaceType::Destroy(ASTContext& C) {
- this->~ObjCInterfaceType();
- C.Deallocate(this);
-}
-
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols)
@@ -366,11 +356,6 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
NumProtocols * sizeof(ObjCProtocolDecl*));
}
-void ObjCObjectTypeImpl::Destroy(ASTContext& C) {
- this->~ObjCObjectTypeImpl();
- C.Deallocate(this);
-}
-
const ObjCObjectType *Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCObjectType's, just return the canonical
// type pointer if it is the right class. There is no typedef information to
@@ -385,11 +370,6 @@ bool Type::isObjCQualifiedInterfaceType() const {
return getAsObjCQualifiedInterfaceType() != 0;
}
-void ObjCObjectPointerType::Destroy(ASTContext& C) {
- this->~ObjCObjectPointerType();
- C.Deallocate(this);
-}
-
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.
@@ -434,9 +414,14 @@ bool Type::isIntegerType() const {
// FIXME: In C++, enum types are never integer types.
if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
return true;
+ return false;
+}
+
+bool Type::hasIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
- return false;
+ else
+ return isIntegerType();
}
/// \brief Determine whether this type is an integral type.
@@ -475,10 +460,13 @@ bool Type::isIntegralOrEnumerationType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
-
- if (isa<EnumType>(CanonicalType))
- return true;
-
+
+ // Check for a complete enum type; incomplete enum types are not properly an
+ // enumeration type in the sense required here.
+ if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
+ if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
+ return true;
+
return false;
}
@@ -523,8 +511,7 @@ bool Type::isAnyCharacterType() const {
/// isSignedIntegerType - Return true if this is an integer type that is
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
-/// an enum decl which has a signed representation, or a vector of signed
-/// integer element type.
+/// an enum decl which has a signed representation
bool Type::isSignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
@@ -534,15 +521,19 @@ bool Type::isSignedIntegerType() const {
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
+ return false;
+}
+
+bool Type::hasSignedIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerType();
- return false;
+ else
+ return isSignedIntegerType();
}
/// isUnsignedIntegerType - Return true if this is an integer type that is
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
-/// decl which has an unsigned representation, or a vector of unsigned integer
-/// element type.
+/// decl which has an unsigned representation
bool Type::isUnsignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
@@ -552,9 +543,14 @@ bool Type::isUnsignedIntegerType() const {
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
+ return false;
+}
+
+bool Type::hasUnsignedIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerType();
- return false;
+ else
+ return isUnsignedIntegerType();
}
bool Type::isFloatingType() const {
@@ -671,10 +667,11 @@ bool Type::isIncompleteType() const {
// An array of unknown size is an incomplete type (C99 6.2.5p22).
return true;
case ObjCObject:
- return cast<ObjCObjectType>(this)->getBaseType()->isIncompleteType();
+ return cast<ObjCObjectType>(CanonicalType)->getBaseType()
+ ->isIncompleteType();
case ObjCInterface:
// ObjC interfaces are incomplete if they are @class, not @interface.
- return cast<ObjCInterfaceType>(this)->getDecl()->isForwardDecl();
+ return cast<ObjCInterfaceType>(CanonicalType)->getDecl()->isForwardDecl();
}
}
@@ -894,15 +891,6 @@ ElaboratedType::~ElaboratedType() {}
DependentNameType::~DependentNameType() {}
DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {}
-void DependentTemplateSpecializationType::Destroy(ASTContext &C) {
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- // FIXME: Not all expressions get cloned, so we can't yet perform
- // this destruction.
- // if (Expr *E = getArg(Arg).getAsExpr())
- // E->Destroy(C);
- }
-}
-
DependentTemplateSpecializationType::DependentTemplateSpecializationType(
ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS, const IdentifierInfo *Name,
@@ -1017,6 +1005,7 @@ llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86StdCall: return "stdcall";
case CC_X86FastCall: return "fastcall";
case CC_X86ThisCall: return "thiscall";
+ case CC_X86Pascal: return "pascal";
}
}
@@ -1108,7 +1097,30 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
: Type(TC, can, D->isDependentType()),
- decl(const_cast<TagDecl*>(D), 0) {}
+ decl(const_cast<TagDecl*>(D)) {}
+
+static TagDecl *getInterestingTagDecl(TagDecl *decl) {
+ for (TagDecl::redecl_iterator I = decl->redecls_begin(),
+ E = decl->redecls_end();
+ I != E; ++I) {
+ if (I->isDefinition() || I->isBeingDefined())
+ return *I;
+ }
+ // If there's no definition (not even in progress), return what we have.
+ return decl;
+}
+
+TagDecl *TagType::getDecl() const {
+ return getInterestingTagDecl(decl);
+}
+
+bool TagType::isBeingDefined() const {
+ return getDecl()->isBeingDefined();
+}
+
+CXXRecordDecl *InjectedClassNameType::getDecl() const {
+ return cast<CXXRecordDecl>(getInterestingTagDecl(Decl));
+}
bool RecordType::classof(const TagType *TT) {
return isa<RecordDecl>(TT->getDecl());
@@ -1196,15 +1208,6 @@ TemplateSpecializationType(TemplateName T,
new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
}
-void TemplateSpecializationType::Destroy(ASTContext& C) {
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- // FIXME: Not all expressions get cloned, so we can't yet perform
- // this destruction.
- // if (Expr *E = getArg(Arg).getAsExpr())
- // E->Destroy(C);
- }
-}
-
void
TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
TemplateName T,
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 4893b384dd10..66578fb3dc49 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -74,20 +74,6 @@ TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
return NextLoc().Visit(TL);
}
-namespace {
- struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> {
- SourceLocation Loc;
- TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {}
-
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
- void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- TyLoc.initializeLocal(Loc); \
- }
-#include "clang/AST/TypeLocNodes.def"
- };
-}
-
/// \brief Initializes a type location, and all of its children
/// recursively, as if the entire tree had been written in the
/// given location.
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index a08ee1ae695d..d3a6b645537c 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -299,6 +299,9 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
case CC_X86ThisCall:
S += " __attribute__((thiscall))";
break;
+ case CC_X86Pascal:
+ S += " __attribute__((pascal))";
+ break;
}
if (Info.getNoReturn())
S += " __attribute__((noreturn))";
@@ -430,9 +433,10 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
Buffer += ' ';
}
+ // Compute the full nested-name-specifier for this type.
+ // In C, this will always be empty except when the type
+ // being printed is anonymous within other Record.
if (!Policy.SuppressScope)
- // Compute the full nested-name-specifier for this type. In C,
- // this will always be empty.
AppendScope(D->getDeclContext(), Buffer);
if (const IdentifierInfo *II = D->getIdentifier())
@@ -463,7 +467,6 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
}
OS << '>';
- OS.flush();
}
// If this is a class template specialization, print the template