summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp569
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CMakeLists.txt4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp161
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp282
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp124
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp429
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp101
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp471
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp89
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Makefile6
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp972
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp132
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateName.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Type.cpp133
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp51
25 files changed, 2614 insertions, 1328 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
index 851f8d1..d41051f 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -31,25 +31,128 @@
using namespace clang;
+unsigned ASTContext::NumImplicitDefaultConstructors;
+unsigned ASTContext::NumImplicitDefaultConstructorsDeclared;
+unsigned ASTContext::NumImplicitCopyConstructors;
+unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
+unsigned ASTContext::NumImplicitCopyAssignmentOperators;
+unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
+unsigned ASTContext::NumImplicitDestructors;
+unsigned ASTContext::NumImplicitDestructorsDeclared;
+
enum FloatingRank {
FloatRank, DoubleRank, LongDoubleRank
};
+void
+ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
+ TemplateTemplateParmDecl *Parm) {
+ ID.AddInteger(Parm->getDepth());
+ ID.AddInteger(Parm->getPosition());
+ // FIXME: Parameter pack
+
+ TemplateParameterList *Params = Parm->getTemplateParameters();
+ ID.AddInteger(Params->size());
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
+ ID.AddInteger(0);
+ ID.AddBoolean(TTP->isParameterPack());
+ continue;
+ }
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ ID.AddInteger(1);
+ // FIXME: Parameter pack
+ ID.AddPointer(NTTP->getType().getAsOpaquePtr());
+ continue;
+ }
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+ ID.AddInteger(2);
+ Profile(ID, TTP);
+ }
+}
+
+TemplateTemplateParmDecl *
+ASTContext::getCanonicalTemplateTemplateParmDecl(
+ TemplateTemplateParmDecl *TTP) {
+ // Check if we already have a canonical template template parameter.
+ llvm::FoldingSetNodeID ID;
+ CanonicalTemplateTemplateParm::Profile(ID, TTP);
+ void *InsertPos = 0;
+ CanonicalTemplateTemplateParm *Canonical
+ = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
+ if (Canonical)
+ return Canonical->getParam();
+
+ // Build a canonical template parameter list.
+ TemplateParameterList *Params = TTP->getTemplateParameters();
+ llvm::SmallVector<NamedDecl *, 4> CanonParams;
+ CanonParams.reserve(Params->size());
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P))
+ CanonParams.push_back(
+ TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(),
+ SourceLocation(), TTP->getDepth(),
+ TTP->getIndex(), 0, false,
+ TTP->isParameterPack()));
+ else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*P))
+ CanonParams.push_back(
+ NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
+ SourceLocation(), NTTP->getDepth(),
+ NTTP->getPosition(), 0,
+ getCanonicalType(NTTP->getType()),
+ 0));
+ else
+ CanonParams.push_back(getCanonicalTemplateTemplateParmDecl(
+ cast<TemplateTemplateParmDecl>(*P)));
+ }
+
+ TemplateTemplateParmDecl *CanonTTP
+ = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
+ SourceLocation(), TTP->getDepth(),
+ TTP->getPosition(), 0,
+ TemplateParameterList::Create(*this, SourceLocation(),
+ SourceLocation(),
+ CanonParams.data(),
+ CanonParams.size(),
+ SourceLocation()));
+
+ // Get the new insert position for the node we care about.
+ Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
+ assert(Canonical == 0 && "Shouldn't be in the map!");
+ (void)Canonical;
+
+ // Create the canonical template template parameter entry.
+ Canonical = new (*this) CanonicalTemplateTemplateParm(CanonTTP);
+ CanonTemplateTemplateParms.InsertNode(Canonical, InsertPos);
+ return CanonTTP;
+}
+
ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
bool FreeMem, unsigned size_reserve) :
- GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),
- NSConstantStringTypeDecl(0),
+ TemplateSpecializationTypes(this_()),
+ DependentTemplateSpecializationTypes(this_()),
+ GlobalNestedNameSpecifier(0), IsInt128Installed(false),
+ CFConstantStringTypeDecl(0), NSConstantStringTypeDecl(0),
ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
+ NullTypeSourceInfo(QualType()),
SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins),
DeclarationNames(*this),
ExternalSource(0), PrintingPolicy(LOpts),
- LastSDM(0, 0) {
+ LastSDM(0, 0),
+ UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
ObjCSelRedefinitionType = QualType();
@@ -88,13 +191,6 @@ ASTContext::~ASTContext() {
Deallocate(&*I++);
}
- for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
- I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
- // Increment in loop to prevent using deallocated memory.
- if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
- R->Destroy(*this);
- }
-
for (llvm::DenseMap<const ObjCContainerDecl*,
const ASTRecordLayout*>::iterator
I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; ) {
@@ -104,6 +200,16 @@ ASTContext::~ASTContext() {
}
}
+ // 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; ) {
+ // 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(),
@@ -155,11 +261,30 @@ void ASTContext::PrintStats() const {
#include "clang/AST/TypeNodes.def"
fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));
-
+
+ // Implicit special member functions.
+ fprintf(stderr, " %u/%u implicit default constructors created\n",
+ NumImplicitDefaultConstructorsDeclared,
+ NumImplicitDefaultConstructors);
+ fprintf(stderr, " %u/%u implicit copy constructors created\n",
+ NumImplicitCopyConstructorsDeclared,
+ NumImplicitCopyConstructors);
+ fprintf(stderr, " %u/%u implicit copy assignment operators created\n",
+ NumImplicitCopyAssignmentOperatorsDeclared,
+ NumImplicitCopyAssignmentOperators);
+ 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();
}
@@ -273,13 +398,14 @@ ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
void
ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
- TemplateSpecializationKind TSK) {
+ TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation) {
assert(Inst->isStaticDataMember() && "Not a static data member");
assert(Tmpl->isStaticDataMember() && "Not a static data member");
assert(!InstantiatedFromStaticDataMember[Inst] &&
"Already noted what static data member was instantiated from");
InstantiatedFromStaticDataMember[Inst]
- = new (*this) MemberSpecializationInfo(Tmpl, TSK);
+ = new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation);
}
NamedDecl *
@@ -358,6 +484,16 @@ ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {
return Pos->second.end();
}
+unsigned
+ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const {
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
+ = OverriddenMethods.find(Method);
+ if (Pos == OverriddenMethods.end())
+ return 0;
+
+ return Pos->second.size();
+}
+
void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
const CXXMethodDecl *Overridden) {
OverriddenMethods[Method].push_back(Overridden);
@@ -414,6 +550,15 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
T = getPointerType(RT->getPointeeType());
}
if (!T->isIncompleteType() && !T->isFunctionType()) {
+ unsigned MinWidth = Target.getLargeArrayMinWidth();
+ unsigned ArrayAlign = Target.getLargeArrayAlign();
+ if (isa<VariableArrayType>(T) && MinWidth != 0)
+ Align = std::max(Align, ArrayAlign);
+ if (ConstantArrayType *CT = dyn_cast<ConstantArrayType>(T)) {
+ unsigned Size = getTypeSize(CT);
+ if (MinWidth != 0 && MinWidth <= Size)
+ Align = std::max(Align, ArrayAlign);
+ }
// Incomplete or function types default to 1.
while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
T = cast<ArrayType>(T)->getElementType();
@@ -762,7 +907,8 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
// Find ivars declared in class extension.
- if (const ObjCCategoryDecl *CDecl = OI->getClassExtension()) {
+ 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);
@@ -827,7 +973,8 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) {
unsigned count = 0;
// Count ivars declared in class extension.
- if (const ObjCCategoryDecl *CDecl = OI->getClassExtension())
+ for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
+ CDecl = CDecl->getNextClassExtension())
count += CDecl->ivar_size();
// Count ivar defined in this class's implementation. This
@@ -1406,7 +1553,7 @@ QualType ASTContext::getIncompleteArrayType(QualType EltTy,
/// getVectorType - Return the unique reference to a vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
- bool IsAltiVec, bool IsPixel) {
+ VectorType::AltiVecSpecific AltiVecSpec) {
BuiltinType *baseType;
baseType = dyn_cast<BuiltinType>(getCanonicalType(vecType).getTypePtr());
@@ -1414,8 +1561,8 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
// Check if we've already instantiated a vector of this type.
llvm::FoldingSetNodeID ID;
- VectorType::Profile(ID, vecType, NumElts, Type::Vector,
- IsAltiVec, IsPixel);
+ VectorType::Profile(ID, vecType, NumElts, Type::Vector, AltiVecSpec);
+
void *InsertPos = 0;
if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(VTP, 0);
@@ -1423,16 +1570,19 @@ 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() || IsAltiVec || IsPixel) {
- Canonical = getVectorType(getCanonicalType(vecType),
- NumElts, false, false);
+ 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
+ Canonical = getVectorType(getCanonicalType(vecType), NumElts,
+ VectorType::NotAltiVec);
// Get the new insert position for the node we care about.
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
}
VectorType *New = new (*this, TypeAlignment)
- VectorType(vecType, NumElts, Canonical, IsAltiVec, IsPixel);
+ VectorType(vecType, NumElts, Canonical, AltiVecSpec);
VectorTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return QualType(New, 0);
@@ -1448,7 +1598,8 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) {
// Check if we've already instantiated a vector of this type.
llvm::FoldingSetNodeID ID;
- VectorType::Profile(ID, vecType, NumElts, Type::ExtVector, false, false);
+ VectorType::Profile(ID, vecType, NumElts, Type::ExtVector,
+ VectorType::NotAltiVec);
void *InsertPos = 0;
if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(VTP, 0);
@@ -1629,8 +1780,7 @@ QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl,
assert(NeedsInjectedClassNameType(Decl));
if (Decl->TypeForDecl) {
assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
- } else if (CXXRecordDecl *PrevDecl
- = cast_or_null<CXXRecordDecl>(Decl->getPreviousDeclaration())) {
+ } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDeclaration()) {
assert(PrevDecl->TypeForDecl && "previous declaration has no type");
Decl->TypeForDecl = PrevDecl->TypeForDecl;
assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
@@ -1658,11 +1808,11 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) {
assert(!Record->getPreviousDeclaration() &&
"struct/union has previous declaration");
assert(!NeedsInjectedClassNameType(Record));
- Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Record);
+ return getRecordType(Record);
} else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) {
assert(!Enum->getPreviousDeclaration() &&
"enum has previous declaration");
- Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum);
+ return getEnumType(Enum);
} else if (const UnresolvedUsingTypenameDecl *Using =
dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using);
@@ -1675,16 +1825,42 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) {
/// getTypedefType - Return the unique reference to the type for the
/// specified typename decl.
-QualType ASTContext::getTypedefType(const TypedefDecl *Decl) {
+QualType
+ASTContext::getTypedefType(const TypedefDecl *Decl, QualType Canonical) {
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
- QualType Canonical = getCanonicalType(Decl->getUnderlyingType());
+ if (Canonical.isNull())
+ Canonical = getCanonicalType(Decl->getUnderlyingType());
Decl->TypeForDecl = new(*this, TypeAlignment)
TypedefType(Type::Typedef, Decl, Canonical);
Types.push_back(Decl->TypeForDecl);
return QualType(Decl->TypeForDecl, 0);
}
+QualType ASTContext::getRecordType(const RecordDecl *Decl) {
+ if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+
+ if (const RecordDecl *PrevDecl = Decl->getPreviousDeclaration())
+ if (PrevDecl->TypeForDecl)
+ return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
+
+ Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Decl);
+ Types.push_back(Decl->TypeForDecl);
+ return QualType(Decl->TypeForDecl, 0);
+}
+
+QualType ASTContext::getEnumType(const EnumDecl *Decl) {
+ if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+
+ if (const EnumDecl *PrevDecl = Decl->getPreviousDeclaration())
+ if (PrevDecl->TypeForDecl)
+ return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
+
+ Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Decl);
+ Types.push_back(Decl->TypeForDecl);
+ return QualType(Decl->TypeForDecl, 0);
+}
+
/// \brief Retrieve a substitution-result type.
QualType
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
@@ -1763,8 +1939,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
const TemplateArgumentListInfo &Args,
- QualType Canon,
- bool IsCurrentInstantiation) {
+ QualType Canon) {
unsigned NumArgs = Args.size();
llvm::SmallVector<TemplateArgument, 4> ArgVec;
@@ -1773,56 +1948,18 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
ArgVec.push_back(Args[i].getArgument());
return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs,
- Canon, IsCurrentInstantiation);
+ Canon);
}
QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
const TemplateArgument *Args,
unsigned NumArgs,
- QualType Canon,
- bool IsCurrentInstantiation) {
+ QualType Canon) {
if (!Canon.isNull())
Canon = getCanonicalType(Canon);
- else {
- assert(!IsCurrentInstantiation &&
- "current-instantiation specializations should always "
- "have a canonical type");
-
- // Build the canonical template specialization type.
- TemplateName CanonTemplate = getCanonicalTemplateName(Template);
- llvm::SmallVector<TemplateArgument, 4> CanonArgs;
- CanonArgs.reserve(NumArgs);
- for (unsigned I = 0; I != NumArgs; ++I)
- CanonArgs.push_back(getCanonicalTemplateArgument(Args[I]));
-
- // Determine whether this canonical template specialization type already
- // exists.
- llvm::FoldingSetNodeID ID;
- TemplateSpecializationType::Profile(ID, CanonTemplate, false,
- CanonArgs.data(), NumArgs, *this);
-
- void *InsertPos = 0;
- TemplateSpecializationType *Spec
- = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
-
- if (!Spec) {
- // Allocate a new canonical template specialization type.
- void *Mem = Allocate((sizeof(TemplateSpecializationType) +
- sizeof(TemplateArgument) * NumArgs),
- TypeAlignment);
- Spec = new (Mem) TemplateSpecializationType(*this, CanonTemplate, false,
- CanonArgs.data(), NumArgs,
- Canon);
- Types.push_back(Spec);
- TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
- }
-
- if (Canon.isNull())
- Canon = QualType(Spec, 0);
- assert(Canon->isDependentType() &&
- "Non-dependent template-id type must have a canonical type");
- }
+ else
+ Canon = getCanonicalTemplateSpecializationType(Template, Args, NumArgs);
// Allocate the (non-canonical) template specialization type, but don't
// try to unique it: these types typically have location information that
@@ -1831,8 +1968,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
sizeof(TemplateArgument) * NumArgs),
TypeAlignment);
TemplateSpecializationType *Spec
- = new (Mem) TemplateSpecializationType(*this, Template,
- IsCurrentInstantiation,
+ = new (Mem) TemplateSpecializationType(Template,
Args, NumArgs,
Canon);
@@ -1841,6 +1977,44 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
}
QualType
+ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
+ // Build the canonical template specialization type.
+ TemplateName CanonTemplate = getCanonicalTemplateName(Template);
+ llvm::SmallVector<TemplateArgument, 4> CanonArgs;
+ CanonArgs.reserve(NumArgs);
+ for (unsigned I = 0; I != NumArgs; ++I)
+ CanonArgs.push_back(getCanonicalTemplateArgument(Args[I]));
+
+ // Determine whether this canonical template specialization type already
+ // exists.
+ llvm::FoldingSetNodeID ID;
+ TemplateSpecializationType::Profile(ID, CanonTemplate,
+ CanonArgs.data(), NumArgs, *this);
+
+ void *InsertPos = 0;
+ TemplateSpecializationType *Spec
+ = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!Spec) {
+ // Allocate a new canonical template specialization type.
+ void *Mem = Allocate((sizeof(TemplateSpecializationType) +
+ sizeof(TemplateArgument) * NumArgs),
+ TypeAlignment);
+ Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
+ CanonArgs.data(), NumArgs,
+ QualType());
+ Types.push_back(Spec);
+ TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
+ }
+
+ assert(Spec->isDependentType() &&
+ "Non-dependent template-id type must have a canonical type");
+ return QualType(Spec, 0);
+}
+
+QualType
ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
QualType NamedType) {
@@ -1898,44 +2072,69 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
}
QualType
-ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
+ASTContext::getDependentTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
- const TemplateSpecializationType *TemplateId,
- QualType Canon) {
+ const IdentifierInfo *Name,
+ const TemplateArgumentListInfo &Args) {
+ // TODO: avoid this copy
+ llvm::SmallVector<TemplateArgument, 16> ArgCopy;
+ for (unsigned I = 0, E = Args.size(); I != E; ++I)
+ ArgCopy.push_back(Args[I].getArgument());
+ return getDependentTemplateSpecializationType(Keyword, NNS, Name,
+ ArgCopy.size(),
+ ArgCopy.data());
+}
+
+QualType
+ASTContext::getDependentTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ unsigned NumArgs,
+ const TemplateArgument *Args) {
assert(NNS->isDependent() && "nested-name-specifier must be dependent");
llvm::FoldingSetNodeID ID;
- DependentNameType::Profile(ID, Keyword, NNS, TemplateId);
+ DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS,
+ Name, NumArgs, Args);
void *InsertPos = 0;
- DependentNameType *T
- = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
+ DependentTemplateSpecializationType *T
+ = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
return QualType(T, 0);
- if (Canon.isNull()) {
- NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
- QualType CanonType = getCanonicalType(QualType(TemplateId, 0));
- ElaboratedTypeKeyword CanonKeyword = Keyword;
- if (Keyword == ETK_None)
- CanonKeyword = ETK_Typename;
- if (CanonNNS != NNS || CanonKeyword != Keyword ||
- CanonType != QualType(TemplateId, 0)) {
- const TemplateSpecializationType *CanonTemplateId
- = CanonType->getAs<TemplateSpecializationType>();
- assert(CanonTemplateId &&
- "Canonical type must also be a template specialization type");
- Canon = getDependentNameType(CanonKeyword, CanonNNS, CanonTemplateId);
- }
+ NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+
+ ElaboratedTypeKeyword CanonKeyword = Keyword;
+ if (Keyword == ETK_None) CanonKeyword = ETK_Typename;
- DependentNameType *CheckT
- = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(!CheckT && "Typename canonical type is broken"); (void)CheckT;
+ bool AnyNonCanonArgs = false;
+ llvm::SmallVector<TemplateArgument, 16> CanonArgs(NumArgs);
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ CanonArgs[I] = getCanonicalTemplateArgument(Args[I]);
+ if (!CanonArgs[I].structurallyEquals(Args[I]))
+ AnyNonCanonArgs = true;
}
- T = new (*this) DependentNameType(Keyword, NNS, TemplateId, Canon);
+ QualType Canon;
+ if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) {
+ Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS,
+ Name, NumArgs,
+ CanonArgs.data());
+
+ // Find the insert position again.
+ DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) +
+ sizeof(TemplateArgument) * NumArgs),
+ TypeAlignment);
+ T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS,
+ Name, NumArgs, Args, Canon);
Types.push_back(T);
- DependentNameTypes.InsertNode(T, InsertPos);
+ DependentTemplateSpecializationTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
}
@@ -2326,6 +2525,48 @@ QualType ASTContext::getUnqualifiedArrayType(QualType T,
SourceRange());
}
+/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that
+/// may be similar (C++ 4.4), replaces T1 and T2 with the type that
+/// they point to and return true. If T1 and T2 aren't pointer types
+/// or pointer-to-member types, or if they are not similar at this
+/// level, returns false and leaves T1 and T2 unchanged. Top-level
+/// qualifiers on T1 and T2 are ignored. This function will typically
+/// be called in a loop that successively "unwraps" pointer and
+/// pointer-to-member types to compare them at each level.
+bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
+ const PointerType *T1PtrType = T1->getAs<PointerType>(),
+ *T2PtrType = T2->getAs<PointerType>();
+ if (T1PtrType && T2PtrType) {
+ T1 = T1PtrType->getPointeeType();
+ T2 = T2PtrType->getPointeeType();
+ return true;
+ }
+
+ const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
+ *T2MPType = T2->getAs<MemberPointerType>();
+ if (T1MPType && T2MPType &&
+ hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
+ QualType(T2MPType->getClass(), 0))) {
+ T1 = T1MPType->getPointeeType();
+ T2 = T2MPType->getPointeeType();
+ return true;
+ }
+
+ if (getLangOptions().ObjC1) {
+ const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(),
+ *T2OPType = T2->getAs<ObjCObjectPointerType>();
+ if (T1OPType && T2OPType) {
+ T1 = T1OPType->getPointeeType();
+ T2 = T2OPType->getPointeeType();
+ return true;
+ }
+ }
+
+ // FIXME: Block pointers, too?
+
+ return false;
+}
+
DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
if (TemplateDecl *TD = Name.getAsTemplateDecl())
return TD->getDeclName();
@@ -2344,10 +2585,14 @@ DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
}
TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
- // If this template name refers to a template, the canonical
- // template name merely stores the template itself.
- if (TemplateDecl *Template = Name.getAsTemplateDecl())
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template))
+ Template = getCanonicalTemplateTemplateParmDecl(TTP);
+
+ // The canonical template name is the canonical template declaration.
return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl()));
+ }
assert(!Name.getAsOverloadedTemplate());
@@ -2856,6 +3101,10 @@ QualType ASTContext::getObjCFastEnumerationStateType() {
Field->setAccess(AS_public);
ObjCFastEnumerationStateTypeDecl->addDecl(Field);
}
+ if (getLangOptions().CPlusPlus)
+ if (CXXRecordDecl *CXXRD =
+ dyn_cast<CXXRecordDecl>(ObjCFastEnumerationStateTypeDecl))
+ CXXRD->setEmpty(false);
ObjCFastEnumerationStateTypeDecl->completeDefinition();
}
@@ -2981,7 +3230,6 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
bool HasCopyAndDispose = BlockRequiresCopying(Ty);
// FIXME: Move up
- static unsigned int UniqueBlockByRefTypeID = 0;
llvm::SmallString<36> Name;
llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
++UniqueBlockByRefTypeID << '_' << DeclName;
@@ -3033,7 +3281,6 @@ QualType ASTContext::getBlockParmType(
llvm::SmallVectorImpl<const Expr *> &Layout) {
// FIXME: Move up
- static unsigned int UniqueBlockParmTypeID = 0;
llvm::SmallString<36> Name;
llvm::raw_svector_ostream(Name) << "__block_literal_"
<< ++UniqueBlockParmTypeID;
@@ -3122,7 +3369,7 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) {
CharUnits sz = getTypeSizeInChars(type);
// Make all integer and enum types at least as large as an int
- if (sz.isPositive() && type->isIntegralType())
+ if (sz.isPositive() && type->isIntegralOrEnumerationType())
sz = std::max(sz, getTypeSizeInChars(IntTy));
// Treat arrays as pointers, since that's how they're passed in.
else if (type->isArrayType())
@@ -3143,7 +3390,7 @@ void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr,
QualType BlockTy =
Expr->getType()->getAs<BlockPointerType>()->getPointeeType();
// Encode result type.
- getObjCEncodingForType(cast<FunctionType>(BlockTy)->getResultType(), S);
+ getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), S);
// Compute size of all parameters.
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
@@ -3376,13 +3623,74 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
true /* outermost type */);
}
+static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) {
+ switch (T->getAs<BuiltinType>()->getKind()) {
+ default: assert(0 && "Unhandled builtin type kind");
+ case BuiltinType::Void: return 'v';
+ case BuiltinType::Bool: return 'B';
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar: return 'C';
+ case BuiltinType::UShort: return 'S';
+ case BuiltinType::UInt: return 'I';
+ case BuiltinType::ULong:
+ return
+ (const_cast<ASTContext *>(C))->getIntWidth(T) == 32 ? 'L' : 'Q';
+ case BuiltinType::UInt128: return 'T';
+ case BuiltinType::ULongLong: return 'Q';
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar: return 'c';
+ case BuiltinType::Short: return 's';
+ case BuiltinType::WChar:
+ case BuiltinType::Int: return 'i';
+ case BuiltinType::Long:
+ return
+ (const_cast<ASTContext *>(C))->getIntWidth(T) == 32 ? 'l' : 'q';
+ case BuiltinType::LongLong: return 'q';
+ case BuiltinType::Int128: return 't';
+ case BuiltinType::Float: return 'f';
+ case BuiltinType::Double: return 'd';
+ case BuiltinType::LongDouble: return 'd';
+ }
+}
+
static void EncodeBitField(const ASTContext *Context, std::string& S,
- const FieldDecl *FD) {
+ QualType T, const FieldDecl *FD) {
const Expr *E = FD->getBitWidth();
assert(E && "bitfield width not there - getObjCEncodingForTypeImpl");
ASTContext *Ctx = const_cast<ASTContext*>(Context);
- unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue();
S += 'b';
+ // The NeXT runtime encodes bit fields as b followed by the number of bits.
+ // The GNU runtime requires more information; bitfields are encoded as b,
+ // then the offset (in bits) of the first element, then the type of the
+ // bitfield, then the size in bits. For example, in this structure:
+ //
+ // struct
+ // {
+ // int integer;
+ // int flags:2;
+ // };
+ // On a 32-bit system, the encoding for flags would be b2 for the NeXT
+ // runtime, but b32i2 for the GNU runtime. The reason for this extra
+ // information is not especially sensible, but we're stuck with it for
+ // compatibility with GCC, although providing it breaks anything that
+ // actually uses runtime introspection and wants to work on both runtimes...
+ if (!Ctx->getLangOptions().NeXTRuntime) {
+ const RecordDecl *RD = FD->getParent();
+ const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
+ // FIXME: This same linear search is also used in ExprConstant - it might
+ // be better if the FieldDecl stored its offset. We'd be increasing the
+ // size of the object slightly, but saving some time every time it is used.
+ unsigned i = 0;
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; (void)++Field, ++i) {
+ if (*Field == FD)
+ break;
+ }
+ S += llvm::utostr(RL.getFieldOffset(i));
+ S += ObjCEncodingForPrimitiveKind(Context, T);
+ }
+ unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue();
S += llvm::utostr(N);
}
@@ -3393,40 +3701,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
const FieldDecl *FD,
bool OutermostType,
bool EncodingProperty) {
- if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
+ if (T->getAs<BuiltinType>()) {
if (FD && FD->isBitField())
- return EncodeBitField(this, S, FD);
- char encoding;
- switch (BT->getKind()) {
- default: assert(0 && "Unhandled builtin type kind");
- case BuiltinType::Void: encoding = 'v'; break;
- case BuiltinType::Bool: encoding = 'B'; break;
- case BuiltinType::Char_U:
- case BuiltinType::UChar: encoding = 'C'; break;
- case BuiltinType::UShort: encoding = 'S'; break;
- case BuiltinType::UInt: encoding = 'I'; break;
- case BuiltinType::ULong:
- encoding =
- (const_cast<ASTContext *>(this))->getIntWidth(T) == 32 ? 'L' : 'Q';
- break;
- case BuiltinType::UInt128: encoding = 'T'; break;
- case BuiltinType::ULongLong: encoding = 'Q'; break;
- case BuiltinType::Char_S:
- case BuiltinType::SChar: encoding = 'c'; break;
- case BuiltinType::Short: encoding = 's'; break;
- case BuiltinType::Int: encoding = 'i'; break;
- case BuiltinType::Long:
- encoding =
- (const_cast<ASTContext *>(this))->getIntWidth(T) == 32 ? 'l' : 'q';
- break;
- case BuiltinType::LongLong: encoding = 'q'; break;
- case BuiltinType::Int128: encoding = 't'; break;
- case BuiltinType::Float: encoding = 'f'; break;
- case BuiltinType::Double: encoding = 'd'; break;
- case BuiltinType::LongDouble: encoding = 'd'; break;
- }
-
- S += encoding;
+ return EncodeBitField(this, S, T, FD);
+ S += ObjCEncodingForPrimitiveKind(this, T);
return;
}
@@ -3585,7 +3863,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (T->isEnumeralType()) {
if (FD && FD->isBitField())
- EncodeBitField(this, S, FD);
+ EncodeBitField(this, S, T, FD);
else
S += 'i';
return;
@@ -4728,7 +5006,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
// Turn <4 x signed int> -> <4 x unsigned int>
if (const VectorType *VTy = T->getAs<VectorType>())
return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()),
- VTy->getNumElements(), VTy->isAltiVec(), VTy->isPixel());
+ VTy->getNumElements(), VTy->getAltiVecSpecific());
// For enums, we return the unsigned version of the base type.
if (const EnumType *ETy = T->getAs<EnumType>())
@@ -4886,7 +5164,8 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false);
// FIXME: Don't know what to do about AltiVec.
- Type = Context.getVectorType(ElementType, NumElements, false, false);
+ Type = Context.getVectorType(ElementType, NumElements,
+ VectorType::NotAltiVec);
break;
}
case 'X': {
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
index 6ed08d1..8d347d1 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -73,6 +73,7 @@ namespace {
// FIXME: TemplateSpecializationType
QualType VisitElaboratedType(ElaboratedType *T);
// FIXME: DependentNameType
+ // FIXME: DependentTemplateSpecializationType
QualType VisitObjCInterfaceType(ObjCInterfaceType *T);
QualType VisitObjCObjectType(ObjCObjectType *T);
QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T);
@@ -439,9 +440,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
if (Vec1->getNumElements() != Vec2->getNumElements())
return false;
- if (Vec1->isAltiVec() != Vec2->isAltiVec())
- return false;
- if (Vec1->isPixel() != Vec2->isPixel())
+ if (Vec1->getAltiVecSpecific() != Vec2->getAltiVecSpecific())
return false;
break;
}
@@ -619,14 +618,32 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (!IsStructurallyEquivalent(Typename1->getIdentifier(),
Typename2->getIdentifier()))
return false;
- if (!IsStructurallyEquivalent(Context,
- QualType(Typename1->getTemplateId(), 0),
- QualType(Typename2->getTemplateId(), 0)))
- return false;
break;
}
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateSpecializationType *Spec1 =
+ cast<DependentTemplateSpecializationType>(T1);
+ const DependentTemplateSpecializationType *Spec2 =
+ cast<DependentTemplateSpecializationType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Spec1->getQualifier(),
+ Spec2->getQualifier()))
+ return false;
+ if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
+ Spec2->getIdentifier()))
+ return false;
+ if (Spec1->getNumArgs() != Spec2->getNumArgs())
+ return false;
+ for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context,
+ Spec1->getArg(I), Spec2->getArg(I)))
+ return false;
+ }
+ break;
+ }
+
case Type::ObjCInterface: {
const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1);
const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2);
@@ -1172,8 +1189,7 @@ QualType ASTNodeImporter::VisitVectorType(VectorType *T) {
return Importer.getToContext().getVectorType(ToElementType,
T->getNumElements(),
- T->isAltiVec(),
- T->isPixel());
+ T->getAltiVecSpecific());
}
QualType ASTNodeImporter::VisitExtVectorType(ExtVectorType *T) {
@@ -1687,7 +1703,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
// Create the record declaration.
RecordDecl *D2 = AdoptDecl;
if (!D2) {
- if (CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(D)) {
+ if (isa<CXXRecordDecl>(D)) {
CXXRecordDecl *D2CXX = CXXRecordDecl::Create(Importer.getToContext(),
D->getTagKind(),
DC, Loc,
@@ -1695,30 +1711,6 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Importer.Import(D->getTagKeywordLoc()));
D2 = D2CXX;
D2->setAccess(D->getAccess());
-
- if (D->isDefinition()) {
- // Add base classes.
- llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
- for (CXXRecordDecl::base_class_iterator
- Base1 = D1CXX->bases_begin(),
- FromBaseEnd = D1CXX->bases_end();
- Base1 != FromBaseEnd;
- ++Base1) {
- QualType T = Importer.Import(Base1->getType());
- if (T.isNull())
- return 0;
-
- Bases.push_back(
- new (Importer.getToContext())
- CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()),
- Base1->isVirtual(),
- Base1->isBaseOfClass(),
- Base1->getAccessSpecifierAsWritten(),
- T));
- }
- if (!Bases.empty())
- D2CXX->setBases(Bases.data(), Bases.size());
- }
} else {
D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(),
DC, Loc,
@@ -1739,6 +1731,33 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
if (D->isDefinition()) {
D2->startDefinition();
+
+ // Add base classes.
+ if (CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
+ CXXRecordDecl *D1CXX = cast<CXXRecordDecl>(D);
+
+ llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
+ for (CXXRecordDecl::base_class_iterator
+ Base1 = D1CXX->bases_begin(),
+ FromBaseEnd = D1CXX->bases_end();
+ Base1 != FromBaseEnd;
+ ++Base1) {
+ QualType T = Importer.Import(Base1->getType());
+ if (T.isNull())
+ return 0;
+
+ Bases.push_back(
+ new (Importer.getToContext())
+ CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()),
+ Base1->isVirtual(),
+ Base1->isBaseOfClass(),
+ Base1->getAccessSpecifierAsWritten(),
+ T));
+ }
+ if (!Bases.empty())
+ D2CXX->setBases(Bases.data(), Bases.size());
+ }
+
ImportDeclContext(D);
D2->completeDefinition();
}
@@ -2598,8 +2617,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
}
// Import the type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
+ TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo());
+ if (!T)
return 0;
// Create the new property.
@@ -2614,6 +2633,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
LexicalDC->addDecl(ToProperty);
ToProperty->setPropertyAttributes(D->getPropertyAttributes());
+ ToProperty->setPropertyAttributesAsWritten(
+ D->getPropertyAttributesAsWritten());
ToProperty->setGetterName(Importer.Import(D->getGetterName()));
ToProperty->setSetterName(Importer.Import(D->getSetterName()));
ToProperty->setGetterMethodDecl(
diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp
index 0fab22c..b09ba895 100644
--- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp
@@ -24,7 +24,7 @@ void Attr::Destroy(ASTContext &C) {
C.Deallocate((void*)this);
}
-AttrWithString::AttrWithString(Attr::Kind AK, ASTContext &C, llvm::StringRef s)
+AttrWithString::AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s)
: Attr(AK) {
assert(!s.empty());
StrLen = s.size();
@@ -51,7 +51,7 @@ void FormatAttr::setType(ASTContext &C, llvm::StringRef type) {
}
NonNullAttr::NonNullAttr(ASTContext &C, unsigned* arg_nums, unsigned size)
- : Attr(NonNull), ArgNums(0), Size(0) {
+ : Attr(attr::NonNull), ArgNums(0), Size(0) {
if (size == 0)
return;
assert(arg_nums);
@@ -93,6 +93,7 @@ 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)
@@ -200,6 +201,10 @@ 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);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/CMakeLists.txt b/contrib/llvm/tools/clang/lib/AST/CMakeLists.txt
index bce3646..407ed95 100644
--- a/contrib/llvm/tools/clang/lib/AST/CMakeLists.txt
+++ b/contrib/llvm/tools/clang/lib/AST/CMakeLists.txt
@@ -18,6 +18,7 @@ add_clang_library(clangAST
DeclPrinter.cpp
DeclTemplate.cpp
Expr.cpp
+ ExprClassification.cpp
ExprConstant.cpp
ExprCXX.cpp
FullExpr.cpp
@@ -39,4 +40,5 @@ add_clang_library(clangAST
TypePrinter.cpp
)
-add_dependencies(clangAST ClangDiagnosticAST ClangStmtNodes)
+add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList
+ ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
index d616e42..c563c37 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
@@ -90,6 +90,9 @@ bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) cons
}
bool CXXRecordDecl::isVirtuallyDerivedFrom(CXXRecordDecl *Base) const {
+ if (!getNumVBases())
+ return false;
+
CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
/*DetectVirtual=*/false);
@@ -559,22 +562,23 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
for (; OverMethods.first != OverMethods.second; ++OverMethods.first) {
const CXXMethodDecl *CanonOM
= cast<CXXMethodDecl>((*OverMethods.first)->getCanonicalDecl());
+
+ // C++ [class.virtual]p2:
+ // A virtual member function C::vf of a class object S is
+ // a final overrider unless the most derived class (1.8)
+ // of which S is a base class subobject (if any) declares
+ // or inherits another member function that overrides vf.
+ //
+ // Treating this object like the most derived class, we
+ // replace any overrides from base classes with this
+ // overriding virtual function.
+ Overriders[CanonOM].replaceAll(
+ UniqueVirtualMethod(CanonM, SubobjectNumber,
+ InVirtualSubobject));
+
if (CanonOM->begin_overridden_methods()
- == CanonOM->end_overridden_methods()) {
- // C++ [class.virtual]p2:
- // A virtual member function C::vf of a class object S is
- // a final overrider unless the most derived class (1.8)
- // of which S is a base class subobject (if any) declares
- // or inherits another member function that overrides vf.
- //
- // Treating this object like the most derived class, we
- // replace any overrides from base classes with this
- // overriding virtual function.
- Overriders[CanonOM].replaceAll(
- UniqueVirtualMethod(CanonM, SubobjectNumber,
- InVirtualSubobject));
+ == CanonOM->end_overridden_methods())
continue;
- }
// Continue recursion to the methods that this virtual method
// overrides.
@@ -582,6 +586,12 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
CanonOM->end_overridden_methods()));
}
}
+
+ // C++ [class.virtual]p2:
+ // For convenience we say that any virtual function overrides itself.
+ Overriders[CanonM].add(SubobjectNumber,
+ UniqueVirtualMethod(CanonM, SubobjectNumber,
+ InVirtualSubobject));
}
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
index ffdcb47..149938f 100644
--- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -523,6 +523,14 @@ bool NamedDecl::isCXXInstanceMember() const {
// DeclaratorDecl Implementation
//===----------------------------------------------------------------------===//
+template <typename DeclT>
+static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
+ if (decl->getNumTemplateParameterLists() > 0)
+ return decl->getTemplateParameterList(0)->getTemplateLoc();
+ else
+ return decl->getInnerLocStart();
+}
+
DeclaratorDecl::~DeclaratorDecl() {}
void DeclaratorDecl::Destroy(ASTContext &C) {
if (hasExtInfo())
@@ -531,15 +539,8 @@ void DeclaratorDecl::Destroy(ASTContext &C) {
}
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
- if (DeclInfo) {
- TypeLoc TL = getTypeSourceInfo()->getTypeLoc();
- while (true) {
- TypeLoc NextTL = TL.getNextTypeLoc();
- if (!NextTL)
- return TL.getLocalSourceRange().getBegin();
- TL = NextTL;
- }
- }
+ TypeSourceInfo *TSI = getTypeSourceInfo();
+ if (TSI) return TSI->getTypeLoc().getBeginLoc();
return SourceLocation();
}
@@ -573,6 +574,40 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
}
}
+SourceLocation DeclaratorDecl::getOuterLocStart() const {
+ return getTemplateOrInnerLocStart(this);
+}
+
+void
+QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
+ unsigned NumTPLists,
+ TemplateParameterList **TPLists) {
+ assert((NumTPLists == 0 || TPLists != 0) &&
+ "Empty array of template parameters with positive size!");
+ assert((NumTPLists == 0 || NNS) &&
+ "Nonempty array of template parameters with no qualifier!");
+
+ // Free previous template parameters (if any).
+ if (NumTemplParamLists > 0) {
+ Context.Deallocate(TemplParamLists);
+ TemplParamLists = 0;
+ NumTemplParamLists = 0;
+ }
+ // Set info on matched template parameter lists (if any).
+ if (NumTPLists > 0) {
+ TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
+ NumTemplParamLists = NumTPLists;
+ for (unsigned i = NumTPLists; i-- > 0; )
+ TemplParamLists[i] = TPLists[i];
+ }
+}
+
+void QualifierInfo::Destroy(ASTContext &Context) {
+ // FIXME: Deallocate template parameter lists themselves!
+ if (TemplParamLists)
+ Context.Deallocate(TemplParamLists);
+}
+
//===----------------------------------------------------------------------===//
// VarDecl Implementation
//===----------------------------------------------------------------------===//
@@ -613,14 +648,17 @@ void VarDecl::Destroy(ASTContext& C) {
VarDecl::~VarDecl() {
}
-SourceRange VarDecl::getSourceRange() const {
+SourceLocation VarDecl::getInnerLocStart() const {
SourceLocation Start = getTypeSpecStartLoc();
if (Start.isInvalid())
Start = getLocation();
-
+ return Start;
+}
+
+SourceRange VarDecl::getSourceRange() const {
if (getInit())
- return SourceRange(Start, getInit()->getLocEnd());
- return SourceRange(Start, getLocation());
+ return SourceRange(getOuterLocStart(), getInit()->getLocEnd());
+ return SourceRange(getOuterLocStart(), getLocation());
}
bool VarDecl::isExternC() const {
@@ -678,7 +716,15 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
// AST for 'extern "C" int foo;' is annotated with 'extern'.
if (hasExternalStorage())
return DeclarationOnly;
-
+
+ if (getStorageClassAsWritten() == Extern ||
+ getStorageClassAsWritten() == PrivateExtern) {
+ for (const VarDecl *PrevVar = getPreviousDeclaration();
+ PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) {
+ if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit())
+ return DeclarationOnly;
+ }
+ }
// C99 6.9.2p2:
// A declaration of an object that has file scope without an initializer,
// and without a storage class specifier or the scs 'static', constitutes
@@ -697,7 +743,7 @@ VarDecl *VarDecl::getActingDefinition() {
if (Kind != TentativeDefinition)
return 0;
- VarDecl *LastTentative = false;
+ VarDecl *LastTentative = 0;
VarDecl *First = getFirstDeclaration();
for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end();
I != E; ++I) {
@@ -907,6 +953,17 @@ bool FunctionDecl::isVariadic() const {
return false;
}
+bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+ if (I->Body) {
+ Definition = *I;
+ return true;
+ }
+ }
+
+ return false;
+}
+
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
if (I->Body) {
@@ -1107,11 +1164,11 @@ bool FunctionDecl::isInlined() const {
}
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
- Stmt *Pattern = 0;
+ bool HasPattern = false;
if (PatternDecl)
- Pattern = PatternDecl->getBody(PatternDecl);
+ HasPattern = PatternDecl->hasBody(PatternDecl);
- if (Pattern && PatternDecl)
+ if (HasPattern && PatternDecl)
return PatternDecl->isInlined();
return false;
@@ -1197,6 +1254,23 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
return 0;
}
+FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
+ if (TemplateOrSpecialization.isNull())
+ return TK_NonTemplate;
+ if (TemplateOrSpecialization.is<FunctionTemplateDecl *>())
+ return TK_FunctionTemplate;
+ if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
+ return TK_MemberSpecialization;
+ if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
+ return TK_FunctionTemplateSpecialization;
+ if (TemplateOrSpecialization.is
+ <DependentFunctionTemplateSpecializationInfo*>())
+ return TK_DependentFunctionTemplateSpecialization;
+
+ assert(false && "Did we miss a TemplateOrSpecialization type?");
+ return TK_NonTemplate;
+}
+
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
return cast<FunctionDecl>(Info->getInstantiatedFrom());
@@ -1239,15 +1313,15 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
// Find the actual template from which we will instantiate.
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
- Stmt *Pattern = 0;
+ bool HasPattern = false;
if (PatternDecl)
- Pattern = PatternDecl->getBody(PatternDecl);
+ HasPattern = PatternDecl->hasBody(PatternDecl);
// C++0x [temp.explicit]p9:
// Except for inline functions, other explicit instantiation declarations
// have the effect of suppressing the implicit instantiation of the entity
// to which they refer.
- if (!Pattern || !PatternDecl)
+ if (!HasPattern || !PatternDecl)
return true;
return PatternDecl->isInlined();
@@ -1304,7 +1378,8 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
const TemplateArgumentList *TemplateArgs,
void *InsertPos,
TemplateSpecializationKind TSK,
- const TemplateArgumentListInfo *TemplateArgsAsWritten) {
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation PointOfInstantiation) {
assert(TSK != TSK_Undeclared &&
"Must specify the type of function template specialization");
FunctionTemplateSpecializationInfo *Info
@@ -1317,6 +1392,7 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
Info->Template.setInt(TSK - 1);
Info->TemplateArguments = TemplateArgs;
Info->TemplateArgumentsAsWritten = TemplateArgsAsWritten;
+ Info->PointOfInstantiation = PointOfInstantiation;
TemplateOrSpecialization = Info;
// Insert this function template specialization into the set of known
@@ -1336,6 +1412,28 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
}
void
+FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
+ unsigned NumTemplateArgs,
+ const TemplateArgument *TemplateArgs,
+ TemplateSpecializationKind TSK,
+ unsigned NumTemplateArgsAsWritten,
+ TemplateArgumentLoc *TemplateArgsAsWritten,
+ SourceLocation LAngleLoc,
+ SourceLocation RAngleLoc,
+ SourceLocation PointOfInstantiation) {
+ ASTContext &Ctx = getASTContext();
+ TemplateArgumentList *TemplArgs
+ = new (Ctx) TemplateArgumentList(Ctx, TemplateArgs, NumTemplateArgs);
+ TemplateArgumentListInfo *TemplArgsInfo
+ = new (Ctx) TemplateArgumentListInfo(LAngleLoc, RAngleLoc);
+ for (unsigned i=0; i != NumTemplateArgsAsWritten; ++i)
+ TemplArgsInfo->addArgument(TemplateArgsAsWritten[i]);
+
+ setFunctionTemplateSpecialization(Template, TemplArgs, /*InsertPos=*/0, TSK,
+ TemplArgsInfo, PointOfInstantiation);
+}
+
+void
FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
const UnresolvedSetImpl &Templates,
const TemplateArgumentListInfo &TemplateArgs) {
@@ -1427,7 +1525,7 @@ bool FunctionDecl::isOutOfLine() const {
// class template, check whether that member function was defined out-of-line.
if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
const FunctionDecl *Definition;
- if (FD->getBody(Definition))
+ if (FD->hasBody(Definition))
return Definition->isOutOfLine();
}
@@ -1435,7 +1533,7 @@ bool FunctionDecl::isOutOfLine() const {
// check whether that function template was defined out-of-line.
if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
const FunctionDecl *Definition;
- if (FunTmpl->getTemplatedDecl()->getBody(Definition))
+ if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
return Definition->isOutOfLine();
}
@@ -1472,9 +1570,13 @@ void TagDecl::Destroy(ASTContext &C) {
TypeDecl::Destroy(C);
}
+SourceLocation TagDecl::getOuterLocStart() const {
+ return getTemplateOrInnerLocStart(this);
+}
+
SourceRange TagDecl::getSourceRange() const {
SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
- return SourceRange(TagKeywordLoc, E);
+ return SourceRange(getOuterLocStart(), E);
}
TagDecl* TagDecl::getCanonicalDecl() {
@@ -1569,6 +1671,10 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
return Enum;
}
+EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation());
+}
+
void EnumDecl::Destroy(ASTContext& C) {
TagDecl::Destroy(C);
}
@@ -1608,6 +1714,11 @@ RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
return R;
}
+RecordDecl *RecordDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), 0, 0,
+ SourceLocation());
+}
+
RecordDecl::~RecordDecl() {
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
index 42a3726..d4f997d 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -35,16 +35,18 @@ using namespace clang;
// Statistics
//===----------------------------------------------------------------------===//
-#define DECL(Derived, Base) static int n##Derived##s = 0;
-#include "clang/AST/DeclNodes.def"
+#define DECL(DERIVED, BASE) static int n##DERIVED##s = 0;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
static bool StatSwitch = false;
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
- default: assert(0 && "Declaration not in DeclNodes.def!");
-#define DECL(Derived, Base) case Derived: return #Derived;
-#include "clang/AST/DeclNodes.def"
+ default: assert(0 && "Declaration not in DeclNodes.inc!");
+#define DECL(DERIVED, BASE) case DERIVED: return #DERIVED;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
}
}
@@ -60,9 +62,10 @@ void Decl::setInvalidDecl(bool Invalid) {
const char *DeclContext::getDeclKindName() const {
switch (DeclKind) {
- default: assert(0 && "Declaration context not in DeclNodes.def!");
-#define DECL(Derived, Base) case Decl::Derived: return #Derived;
-#include "clang/AST/DeclNodes.def"
+ default: assert(0 && "Declaration context not in DeclNodes.inc!");
+#define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
}
}
@@ -75,28 +78,31 @@ void Decl::PrintStats() {
fprintf(stderr, "*** Decl Stats:\n");
int totalDecls = 0;
-#define DECL(Derived, Base) totalDecls += n##Derived##s;
-#include "clang/AST/DeclNodes.def"
+#define DECL(DERIVED, BASE) totalDecls += n##DERIVED##s;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
fprintf(stderr, " %d decls total.\n", totalDecls);
int totalBytes = 0;
-#define DECL(Derived, Base) \
- if (n##Derived##s > 0) { \
- totalBytes += (int)(n##Derived##s * sizeof(Derived##Decl)); \
- fprintf(stderr, " %d " #Derived " decls, %d each (%d bytes)\n", \
- n##Derived##s, (int)sizeof(Derived##Decl), \
- (int)(n##Derived##s * sizeof(Derived##Decl))); \
+#define DECL(DERIVED, BASE) \
+ if (n##DERIVED##s > 0) { \
+ totalBytes += (int)(n##DERIVED##s * sizeof(DERIVED##Decl)); \
+ fprintf(stderr, " %d " #DERIVED " decls, %d each (%d bytes)\n", \
+ n##DERIVED##s, (int)sizeof(DERIVED##Decl), \
+ (int)(n##DERIVED##s * sizeof(DERIVED##Decl))); \
}
-#include "clang/AST/DeclNodes.def"
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
fprintf(stderr, "Total bytes = %d\n", totalBytes);
}
-void Decl::addDeclKind(Kind k) {
+void Decl::add(Kind k) {
switch (k) {
- default: assert(0 && "Declaration not in DeclNodes.def!");
-#define DECL(Derived, Base) case Derived: ++n##Derived##s; break;
-#include "clang/AST/DeclNodes.def"
+ default: assert(0 && "Declaration not in DeclNodes.inc!");
+#define DECL(DERIVED, BASE) case DERIVED: ++n##DERIVED##s; break;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
}
}
@@ -206,17 +212,17 @@ ASTContext &Decl::getASTContext() const {
return getTranslationUnitDecl()->getASTContext();
}
-bool Decl::isUsed() const {
+bool Decl::isUsed(bool CheckUsedAttr) const {
if (Used)
return true;
// Check for used attribute.
- if (hasAttr<UsedAttr>())
+ if (CheckUsedAttr && hasAttr<UsedAttr>())
return true;
// Check redeclarations for used attribute.
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
- if (I->hasAttr<UsedAttr>() || I->Used)
+ if ((CheckUsedAttr && I->hasAttr<UsedAttr>()) || I->Used)
return true;
}
@@ -285,6 +291,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
// Never have names.
case Friend:
case FriendTemplate:
+ case AccessSpec:
case LinkageSpec:
case FileScopeAsm:
case StaticAssert:
@@ -307,9 +314,20 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
return 0;
}
+void Decl::initAttrs(Attr *attrs) {
+ assert(!HasAttrs && "Decl already contains attrs.");
+
+ Attr *&AttrBlank = getASTContext().getDeclAttrs(this);
+ assert(AttrBlank == 0 && "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;
@@ -354,7 +372,6 @@ void Decl::swapAttrs(Decl *RHS) {
RHS->HasAttrs = true;
}
-
void Decl::Destroy(ASTContext &C) {
// Free attributes for this decl.
if (HasAttrs) {
@@ -392,16 +409,18 @@ void Decl::Destroy(ASTContext &C) {
Decl *Decl::castFromDeclContext (const DeclContext *D) {
Decl::Kind DK = D->getDeclKind();
switch(DK) {
-#define DECL_CONTEXT(Name) \
- case Decl::Name: \
- return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
-#define DECL_CONTEXT_BASE(Name)
-#include "clang/AST/DeclNodes.def"
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT(NAME) \
+ case Decl::NAME: \
+ return static_cast<NAME##Decl*>(const_cast<DeclContext*>(D));
+#define DECL_CONTEXT_BASE(NAME)
+#include "clang/AST/DeclNodes.inc"
default:
-#define DECL_CONTEXT_BASE(Name) \
- if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \
- return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
-#include "clang/AST/DeclNodes.def"
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT_BASE(NAME) \
+ if (DK >= first##NAME && DK <= last##NAME) \
+ return static_cast<NAME##Decl*>(const_cast<DeclContext*>(D));
+#include "clang/AST/DeclNodes.inc"
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
@@ -410,46 +429,51 @@ Decl *Decl::castFromDeclContext (const DeclContext *D) {
DeclContext *Decl::castToDeclContext(const Decl *D) {
Decl::Kind DK = D->getKind();
switch(DK) {
-#define DECL_CONTEXT(Name) \
- case Decl::Name: \
- return static_cast<Name##Decl*>(const_cast<Decl*>(D));
-#define DECL_CONTEXT_BASE(Name)
-#include "clang/AST/DeclNodes.def"
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT(NAME) \
+ case Decl::NAME: \
+ return static_cast<NAME##Decl*>(const_cast<Decl*>(D));
+#define DECL_CONTEXT_BASE(NAME)
+#include "clang/AST/DeclNodes.inc"
default:
-#define DECL_CONTEXT_BASE(Name) \
- if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \
- return static_cast<Name##Decl*>(const_cast<Decl*>(D));
-#include "clang/AST/DeclNodes.def"
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT_BASE(NAME) \
+ if (DK >= first##NAME && DK <= last##NAME) \
+ return static_cast<NAME##Decl*>(const_cast<Decl*>(D));
+#include "clang/AST/DeclNodes.inc"
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
}
-CompoundStmt* Decl::getCompoundBody() const {
- return dyn_cast_or_null<CompoundStmt>(getBody());
-}
-
SourceLocation Decl::getBodyRBrace() const {
- Stmt *Body = getBody();
- if (!Body)
+ // Special handling of FunctionDecl to avoid de-serializing the body from PCH.
+ // FunctionDecl stores EndRangeLoc for this purpose.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) {
+ const FunctionDecl *Definition;
+ if (FD->hasBody(Definition))
+ return Definition->getSourceRange().getEnd();
return SourceLocation();
- if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
- return CS->getRBracLoc();
- assert(isa<CXXTryStmt>(Body) &&
- "Body can only be CompoundStmt or CXXTryStmt");
- return cast<CXXTryStmt>(Body)->getSourceRange().getEnd();
+ }
+
+ if (Stmt *Body = getBody())
+ return Body->getSourceRange().getEnd();
+
+ return SourceLocation();
}
#ifndef NDEBUG
void Decl::CheckAccessDeclContext() const {
+ // FIXME: Disable this until rdar://8146294 "access specifier for inner class
+ // templates is not set or checked" is fixed.
+ return;
// Suppress this check if any of the following hold:
// 1. this is the translation unit (and thus has no parent)
// 2. this is a template parameter (and thus doesn't belong to its context)
- // 3. this is a ParmVarDecl (which can be in a record context during
- // the brief period between its creation and the creation of the
- // FunctionDecl)
- // 4. the context is not a record
+ // 3. the context is not a record
+ // 4. it's invalid
if (isa<TranslationUnitDecl>(this) ||
+ isa<TemplateTypeParmDecl>(this) ||
!isa<CXXRecordDecl>(getDeclContext()) ||
isInvalidDecl())
return;
@@ -466,16 +490,18 @@ void Decl::CheckAccessDeclContext() const {
bool DeclContext::classof(const Decl *D) {
switch (D->getKind()) {
-#define DECL_CONTEXT(Name) case Decl::Name:
-#define DECL_CONTEXT_BASE(Name)
-#include "clang/AST/DeclNodes.def"
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT(NAME) case Decl::NAME:
+#define DECL_CONTEXT_BASE(NAME)
+#include "clang/AST/DeclNodes.inc"
return true;
default:
-#define DECL_CONTEXT_BASE(Name) \
- if (D->getKind() >= Decl::Name##First && \
- D->getKind() <= Decl::Name##Last) \
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT_BASE(NAME) \
+ if (D->getKind() >= Decl::first##NAME && \
+ D->getKind() <= Decl::last##NAME) \
return true;
-#include "clang/AST/DeclNodes.def"
+#include "clang/AST/DeclNodes.inc"
return false;
}
}
@@ -537,7 +563,7 @@ bool DeclContext::isTransparentContext() const {
return true; // FIXME: Check for C++0x scoped enums
else if (DeclKind == Decl::LinkageSpec)
return true;
- else if (DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast)
+ 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
@@ -581,7 +607,7 @@ DeclContext *DeclContext::getPrimaryContext() {
return this;
default:
- if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
+ if (DeclKind >= Decl::firstTag && DeclKind <= Decl::lastTag) {
// If this is a tag type that has a definition or is currently
// being defined, that definition is our primary context.
TagDecl *Tag = cast<TagDecl>(this);
@@ -602,7 +628,7 @@ DeclContext *DeclContext::getPrimaryContext() {
return Tag;
}
- assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
+ assert(DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction &&
"Unknown DeclContext kind");
return this;
}
@@ -626,9 +652,8 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
ExternalASTSource *Source = getParentASTContext().getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
- llvm::SmallVector<uint32_t, 64> Decls;
- if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this),
- Decls))
+ llvm::SmallVector<Decl*, 64> Decls;
+ if (Source->FindExternalLexicalDecls(this, Decls))
return;
// There is no longer any lexical storage in this context
@@ -642,7 +667,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
Decl *FirstNewDecl = 0;
Decl *PrevDecl = 0;
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- Decl *D = Source->GetDecl(Decls[I]);
+ Decl *D = Decls[I];
if (PrevDecl)
PrevDecl->NextDeclInContext = D;
else
@@ -659,28 +684,83 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
LastDecl = PrevDecl;
}
-void
-DeclContext::LoadVisibleDeclsFromExternalStorage() const {
- DeclContext *This = const_cast<DeclContext *>(this);
- ExternalASTSource *Source = getParentASTContext().getExternalSource();
- assert(hasExternalVisibleStorage() && Source && "No external storage?");
+DeclContext::lookup_result
+ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name) {
+ ASTContext &Context = DC->getParentASTContext();
+ StoredDeclsMap *Map;
+ if (!(Map = DC->LookupPtr))
+ Map = DC->CreateStoredDeclsMap(Context);
+
+ StoredDeclsList &List = (*Map)[Name];
+ assert(List.isNull());
+ (void) List;
+
+ return DeclContext::lookup_result();
+}
- llvm::SmallVector<VisibleDeclaration, 64> Decls;
- if (Source->ReadDeclsVisibleInContext(This, Decls))
- return;
+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);
+}
- // There is no longer any visible storage in this context
- ExternalVisibleStorage = false;
+DeclContext::lookup_result
+ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls) {
+ ASTContext &Context = DC->getParentASTContext();;
- // Load the declaration IDs for all of the names visible in this
- // context.
- assert(!LookupPtr && "Have a lookup map before de-serialization?");
- StoredDeclsMap *Map = CreateStoredDeclsMap(getParentASTContext());
+ StoredDeclsMap *Map;
+ if (!(Map = DC->LookupPtr))
+ Map = DC->CreateStoredDeclsMap(Context);
+
+ 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]);
+ }
+
+ return List.getLookupResult(Context);
+}
+
+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::SetExternalVisibleDecls(const DeclContext *DC,
+ const llvm::SmallVectorImpl<NamedDecl*> &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) {
+ StoredDeclsList &List = Map[Decls[I]->getDeclName()];
+ if (List.isNull())
+ List.setOnlyValue(Decls[I]);
+ else
+ List.AddSubsequentDecl(Decls[I]);
+ }
+}
+
DeclContext::decl_iterator DeclContext::decls_begin() const {
if (hasExternalLexicalStorage())
LoadLexicalDeclsFromExternalStorage();
@@ -801,8 +881,17 @@ DeclContext::lookup(DeclarationName Name) {
if (PrimaryContext != this)
return PrimaryContext->lookup(Name);
- if (hasExternalVisibleStorage())
- LoadVisibleDeclsFromExternalStorage();
+ if (hasExternalVisibleStorage()) {
+ // Check to see if we've already cached the lookup results.
+ if (LookupPtr) {
+ StoredDeclsMap::iterator I = LookupPtr->find(Name);
+ if (I != LookupPtr->end())
+ return I->second.getLookupResult(getParentASTContext());
+ }
+
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ return Source->FindExternalVisibleDeclsByName(this, Name);
+ }
/// If there is no lookup data structure, build one now by walking
/// all of the linked DeclContexts (in declaration order!) and
@@ -858,9 +947,10 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
}
// If we already have a lookup data structure, perform the insertion
- // into it. Otherwise, be lazy and don't build that structure until
- // someone asks for it.
- if (LookupPtr || !Recoverable)
+ // into it. If we haven't deserialized externally stored decls, deserialize
+ // them so we can add the decl. Otherwise, be lazy and don't build that
+ // structure until someone asks for it.
+ if (LookupPtr || !Recoverable || hasExternalVisibleStorage())
makeDeclVisibleInContextImpl(D);
// If we are a transparent context, insert into our parent context,
@@ -880,6 +970,12 @@ 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();
@@ -932,7 +1028,7 @@ void StoredDeclsList::materializeDecls(ASTContext &Context) {
ExternalASTSource *Source = Context.getExternalSource();
assert(Source && "No external AST source available!");
- Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID));
+ Data = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(DeclID));
break;
}
@@ -944,7 +1040,7 @@ void StoredDeclsList::materializeDecls(ASTContext &Context) {
assert(Source && "No external AST source available!");
for (unsigned I = 0, N = Vector.size(); I != N; ++I)
- Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I]));
+ Vector[I] = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(Vector[I]));
Data = (Data & ~0x03) | DK_Decl_Vector;
break;
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
index cd7afd9..dd0fe08 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -32,6 +32,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
Abstract(false), HasTrivialConstructor(true),
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
+ DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false),
+ DeclaredCopyAssignment(false), DeclaredDestructor(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
Definition(D), FirstFriend(0) {
}
@@ -58,6 +60,11 @@ CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
return R;
}
+CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), 0, 0,
+ SourceLocation());
+}
+
CXXRecordDecl::~CXXRecordDecl() {
}
@@ -159,6 +166,29 @@ bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
return getCopyConstructor(Context, Qualifiers::Const) != 0;
}
+/// \brief Perform a simplistic form of overload resolution that only considers
+/// cv-qualifiers on a single parameter, and return the best overload candidate
+/// (if there is one).
+static CXXMethodDecl *
+GetBestOverloadCandidateSimple(
+ const llvm::SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) {
+ if (Cands.empty())
+ return 0;
+ if (Cands.size() == 1)
+ return Cands[0].first;
+
+ unsigned Best = 0, N = Cands.size();
+ for (unsigned I = 1; I != N; ++I)
+ if (Cands[Best].second.isSupersetOf(Cands[I].second))
+ Best = I;
+
+ for (unsigned I = 1; I != N; ++I)
+ if (Cands[Best].second.isSupersetOf(Cands[I].second))
+ return 0;
+
+ return Cands[Best].first;
+}
+
CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
unsigned TypeQuals) const{
QualType ClassType
@@ -167,6 +197,7 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
unsigned FoundTQs;
+ llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found;
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName);
Con != ConEnd; ++Con) {
@@ -175,61 +206,68 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
if (isa<FunctionTemplateDecl>(*Con))
continue;
- if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(FoundTQs)) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isCopyConstructor(FoundTQs)) {
if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) ||
(!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const)))
- return cast<CXXConstructorDecl>(*Con);
-
+ Found.push_back(std::make_pair(
+ const_cast<CXXConstructorDecl *>(Constructor),
+ Qualifiers::fromCVRMask(FoundTQs)));
}
}
- return 0;
+
+ return cast_or_null<CXXConstructorDecl>(
+ GetBestOverloadCandidateSimple(Found));
}
-bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context,
- const CXXMethodDecl *& MD) const {
- QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
- const_cast<CXXRecordDecl*>(this)));
- DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
-
+CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const {
+ ASTContext &Context = getASTContext();
+ QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this));
+ DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+
+ llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found;
DeclContext::lookup_const_iterator Op, OpEnd;
- for (llvm::tie(Op, OpEnd) = this->lookup(OpName);
- Op != OpEnd; ++Op) {
+ for (llvm::tie(Op, OpEnd) = this->lookup(Name); Op != OpEnd; ++Op) {
// C++ [class.copy]p9:
// A user-declared copy assignment operator is a non-static non-template
// member function of class X with exactly one parameter of type X, X&,
// const X&, volatile X& or const volatile X&.
const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op);
- if (!Method)
+ if (!Method || Method->isStatic() || Method->getPrimaryTemplate())
continue;
-
- if (Method->isStatic())
- continue;
- if (Method->getPrimaryTemplate())
- continue;
- const FunctionProtoType *FnType =
- Method->getType()->getAs<FunctionProtoType>();
+
+ const FunctionProtoType *FnType
+ = Method->getType()->getAs<FunctionProtoType>();
assert(FnType && "Overloaded operator has no prototype.");
// Don't assert on this; an invalid decl might have been left in the AST.
if (FnType->getNumArgs() != 1 || FnType->isVariadic())
continue;
- bool AcceptsConst = true;
+
QualType ArgType = FnType->getArgType(0);
+ Qualifiers Quals;
if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()) {
ArgType = Ref->getPointeeType();
- // Is it a non-const lvalue reference?
- if (!ArgType.isConstQualified())
- AcceptsConst = false;
+ // If we have a const argument and we have a reference to a non-const,
+ // this function does not match.
+ if (ArgIsConst && !ArgType.isConstQualified())
+ continue;
+
+ Quals = ArgType.getQualifiers();
+ } else {
+ // By-value copy-assignment operators are treated like const X&
+ // copy-assignment operators.
+ Quals = Qualifiers::fromCVRMask(Qualifiers::Const);
}
- if (!Context.hasSameUnqualifiedType(ArgType, ClassType))
+
+ if (!Context.hasSameUnqualifiedType(ArgType, Class))
continue;
- MD = Method;
- // We have a single argument of type cv X or cv X&, i.e. we've found the
- // copy assignment operator. Return whether it accepts const arguments.
- return AcceptsConst;
+
+ // Save this copy-assignment operator. It might be "the one".
+ Found.push_back(std::make_pair(const_cast<CXXMethodDecl *>(Method), Quals));
}
- assert(isInvalidDecl() &&
- "No copy assignment operator declared in valid code.");
- return false;
+
+ // Use a simplistic form of overload resolution to find the candidate.
+ return GetBestOverloadCandidateSimple(Found);
}
void
@@ -239,6 +277,9 @@ CXXRecordDecl::addedConstructor(ASTContext &Context,
// Note that we have a user-declared constructor.
data().UserDeclaredConstructor = true;
+ // Note that we have no need of an implicitly-declared default constructor.
+ data().DeclaredDefaultConstructor = true;
+
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with no
// user-declared constructors (12.1) [...].
@@ -258,11 +299,13 @@ CXXRecordDecl::addedConstructor(ASTContext &Context,
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor()) {
data().UserDeclaredCopyConstructor = true;
-
+ data().DeclaredCopyConstructor = true;
+
// C++ [class.copy]p6:
// A copy constructor is trivial if it is implicitly declared.
// FIXME: C++0x: don't do this for "= default" copy constructors.
data().HasTrivialCopyConstructor = false;
+
}
}
@@ -294,7 +337,8 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
// Suppress the implicit declaration of a copy constructor.
data().UserDeclaredCopyAssignment = true;
-
+ data().DeclaredCopyAssignment = true;
+
// C++ [class.copy]p11:
// A copy assignment operator is trivial if it is implicitly declared.
// FIXME: C++0x: don't do this for "= default" copy operators.
@@ -546,7 +590,8 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
}
CXXConstructorDecl *
-CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
+CXXRecordDecl::getDefaultConstructor() {
+ ASTContext &Context = getASTContext();
QualType ClassType = Context.getTypeDeclType(this);
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
@@ -566,7 +611,8 @@ CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
return 0;
}
-CXXDestructorDecl *CXXRecordDecl::getDestructor(ASTContext &Context) const {
+CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
+ ASTContext &Context = getASTContext();
QualType ClassType = Context.getTypeDeclType(this);
DeclarationName Name
@@ -670,6 +716,10 @@ CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const {
return getASTContext().overridden_methods_end(this);
}
+unsigned CXXMethodDecl::size_overridden_methods() const {
+ return getASTContext().overridden_methods_size(this);
+}
+
QualType CXXMethodDecl::getThisType(ASTContext &C) const {
// C++ 9.3.2p1: The type of this in a member function of a class X is X*.
// If the member function is declared const, the type of this is const X*,
@@ -693,7 +743,7 @@ bool CXXMethodDecl::hasInlineBody() const {
CheckFn = this;
const FunctionDecl *fn;
- return CheckFn->getBody(fn) && !fn->isOutOfLine();
+ return CheckFn->hasBody(fn) && !fn->isOutOfLine();
}
CXXBaseOrMemberInitializer::
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
index ab3552d..99bfe40 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
@@ -39,3 +39,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
cast<CXXRecordDecl>(DC)->pushFriendDecl(FD);
return FD;
}
+
+FriendDecl *FriendDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) FriendDecl(Empty);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
index dc4aacd..adb0e7d 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
@@ -223,17 +223,24 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
}
-/// getClassExtension - Find class extension of the given class.
-// FIXME. can speed it up, if need be.
-ObjCCategoryDecl* ObjCInterfaceDecl::getClassExtension() const {
- const ObjCInterfaceDecl* ClassDecl = this;
- for (ObjCCategoryDecl *CDecl = ClassDecl->getCategoryList(); CDecl;
+/// getFirstClassExtension - Find first class extension of the given class.
+ObjCCategoryDecl* ObjCInterfaceDecl::getFirstClassExtension() const {
+ for (ObjCCategoryDecl *CDecl = getCategoryList(); CDecl;
CDecl = CDecl->getNextClassCategory())
if (CDecl->IsClassExtension())
return CDecl;
return 0;
}
+/// getNextClassCategory - Find next class extension in list of categories.
+const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const {
+ for (const ObjCCategoryDecl *CDecl = getNextClassCategory(); CDecl;
+ CDecl = CDecl->getNextClassCategory())
+ if (CDecl->IsClassExtension())
+ return CDecl;
+ return 0;
+}
+
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
ObjCInterfaceDecl *&clsDeclared) {
ObjCInterfaceDecl* ClassDecl = this;
@@ -242,11 +249,13 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
clsDeclared = ClassDecl;
return I;
}
- if (const ObjCCategoryDecl *CDecl = ClassDecl->getClassExtension())
+ for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension();
+ CDecl; CDecl = CDecl->getNextClassExtension()) {
if (ObjCIvarDecl *I = CDecl->getIvarDecl(ID)) {
clsDeclared = ClassDecl;
return I;
}
+ }
ClassDecl = ClassDecl->getSuperClass();
}
@@ -887,7 +896,7 @@ ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
IdentifierInfo *Id,
SourceLocation AtLoc,
- QualType T,
+ TypeSourceInfo *T,
PropertyControl propControl) {
return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
index 53949247..765772d 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -183,7 +183,7 @@ void DeclPrinter::Print(AccessSpecifier AS) {
case AS_none: assert(0 && "No access specifier!"); break;
case AS_public: Out << "public"; break;
case AS_protected: Out << "protected"; break;
- case AS_private: Out << " private"; break;
+ case AS_private: Out << "private"; break;
}
}
@@ -195,9 +195,6 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (Indent)
Indentation += Policy.Indentation;
- bool PrintAccess = isa<CXXRecordDecl>(DC);
- AccessSpecifier CurAS = AS_none;
-
llvm::SmallVector<Decl*, 2> Decls;
for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
D != DEnd; ++D) {
@@ -205,21 +202,14 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
// Skip over implicit declarations in pretty-printing mode.
if (D->isImplicit()) continue;
// FIXME: Ugly hack so we don't pretty-print the builtin declaration
- // of __builtin_va_list. There should be some other way to check that.
- if (isa<NamedDecl>(*D) && cast<NamedDecl>(*D)->getNameAsString() ==
- "__builtin_va_list")
- continue;
- }
-
- if (PrintAccess) {
- AccessSpecifier AS = D->getAccess();
-
- if (AS != CurAS) {
- if (Indent)
- this->Indent(Indentation - Policy.Indentation);
- Print(AS);
- Out << ":\n";
- CurAS = AS;
+ // of __builtin_va_list or __[u]int128_t. There should be some other way
+ // to check that.
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
+ if (IdentifierInfo *II = ND->getIdentifier()) {
+ if (II->isStr("__builtin_va_list") ||
+ II->isStr("__int128_t") || II->isStr("__uint128_t"))
+ continue;
+ }
}
}
@@ -251,6 +241,16 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
Decls.push_back(*D);
continue;
}
+
+ if (isa<AccessSpecDecl>(*D)) {
+ Indentation -= Policy.Indentation;
+ this->Indent();
+ Print(D->getAccess());
+ Out << ":\n";
+ Indentation += Policy.Indentation;
+ continue;
+ }
+
this->Indent();
Visit(*D);
@@ -406,7 +406,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
FieldDecl *FD = BMInitializer->getMember();
Out << FD;
} else {
- Out << QualType(BMInitializer->getBaseClass(), 0).getAsString();
+ Out << QualType(BMInitializer->getBaseClass(),
+ 0).getAsString(Policy);
}
Out << "(";
@@ -653,7 +654,11 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) {
Out << "> ";
- Visit(D->getTemplatedDecl());
+ if (isa<TemplateTemplateParmDecl>(D)) {
+ Out << "class " << D->getName();
+ } else {
+ Visit(D->getTemplatedDecl());
+ }
}
//----------------------------------------------------------------------------
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
index 26e291c..9e1d79d 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
@@ -162,37 +162,19 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
TemplateParameterList *Params,
NamedDecl *Decl,
ClassTemplateDecl *PrevDecl) {
- Common *CommonPtr;
- if (PrevDecl)
- CommonPtr = PrevDecl->CommonPtr;
- else {
- CommonPtr = new (C) Common;
- C.AddDeallocation(DeallocateCommon, CommonPtr);
- }
-
- return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl,
- CommonPtr);
-}
-
-ClassTemplateDecl::~ClassTemplateDecl() {
- assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed");
+ ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl);
+ New->setPreviousDeclaration(PrevDecl);
+ return New;
}
void ClassTemplateDecl::Destroy(ASTContext& C) {
- if (!PreviousDeclaration) {
- CommonPtr->~Common();
- C.Deallocate((void*)CommonPtr);
- }
- CommonPtr = 0;
-
- this->~ClassTemplateDecl();
- C.Deallocate((void*)this);
+ Decl::Destroy(C);
}
void ClassTemplateDecl::getPartialSpecializations(
llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) {
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &PartialSpecs
- = CommonPtr->PartialSpecializations;
+ = getPartialSpecializations();
PS.clear();
PS.resize(PartialSpecs.size());
for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
@@ -219,7 +201,8 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) {
}
QualType
-ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
+ClassTemplateDecl::getInjectedClassNameSpecialization() {
+ Common *CommonPtr = getCommonPtr();
if (!CommonPtr->InjectedClassNameType.isNull())
return CommonPtr->InjectedClassNameType;
@@ -227,7 +210,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
// corresponding to template parameter packs should be pack
// expansions. We already say that in 14.6.2.1p2, so it would be
// better to fix that redundancy.
-
+ ASTContext &Context = getASTContext();
TemplateParameterList *Params = getTemplateParameters();
llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
TemplateArgs.reserve(Params->size());
@@ -240,7 +223,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
} else if (NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
Expr *E = new (Context) DeclRefExpr(NTTP,
- NTTP->getType().getNonReferenceType(),
+ NTTP->getType().getNonLValueExprType(Context),
NTTP->getLocation());
TemplateArgs.push_back(TemplateArgument(E));
} else {
@@ -256,6 +239,20 @@ ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
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
//===----------------------------------------------------------------------===//
@@ -269,6 +266,12 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
}
+TemplateTypeParmDecl *
+TemplateTypeParmDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) TemplateTypeParmDecl(0, SourceLocation(), 0, false,
+ QualType(), false);
+}
+
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
return DefaultArgument->getTypeLoc().getSourceRange().getBegin();
}
@@ -294,8 +297,9 @@ NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
}
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
- return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
- : SourceLocation();
+ return hasDefaultArgument()
+ ? getDefaultArgument()->getSourceRange().getBegin()
+ : SourceLocation();
}
//===----------------------------------------------------------------------===//
@@ -393,6 +397,13 @@ TemplateArgumentList::TemplateArgumentList(ASTContext &Context,
}
}
+TemplateArgumentList::TemplateArgumentList(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs)
+ : NumFlatArguments(0), NumStructuredArguments(0) {
+ init(Context, Args, NumArgs);
+}
+
/// Produces a shallow copy of the given template argument list. This
/// assumes that the input argument list outlives it. This takes the list as
/// a pointer to avoid looking like a copy constructor, since this really
@@ -403,6 +414,23 @@ TemplateArgumentList::TemplateArgumentList(const TemplateArgumentList *Other)
StructuredArguments(Other->StructuredArguments.getPointer(), false),
NumStructuredArguments(Other->NumStructuredArguments) { }
+void TemplateArgumentList::init(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
+assert(NumFlatArguments == 0 && NumStructuredArguments == 0 &&
+ "Already initialized!");
+
+NumFlatArguments = NumStructuredArguments = NumArgs;
+TemplateArgument *NewArgs = new (Context) TemplateArgument[NumArgs];
+std::copy(Args, Args+NumArgs, NewArgs);
+FlatArguments.setPointer(NewArgs);
+FlatArguments.setInt(1); // Owns the pointer.
+
+// Just reuse the flat arguments array.
+StructuredArguments.setPointer(NewArgs);
+StructuredArguments.setInt(0); // Doesn't own the pointer.
+}
+
void TemplateArgumentList::Destroy(ASTContext &C) {
if (FlatArguments.getInt())
C.Deallocate((void*)FlatArguments.getPointer());
@@ -425,11 +453,17 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
SpecializedTemplate->getIdentifier(),
PrevDecl),
SpecializedTemplate(SpecializedTemplate),
- TypeAsWritten(0),
+ ExplicitInfo(0),
TemplateArgs(Context, Builder, /*TakeArgs=*/true),
SpecializationKind(TSK_Undeclared) {
}
+ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(Kind DK)
+ : CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), 0, 0),
+ ExplicitInfo(0),
+ SpecializationKind(TSK_Undeclared) {
+}
+
ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
DeclContext *DC, SourceLocation L,
@@ -447,7 +481,15 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
return Result;
}
+ClassTemplateSpecializationDecl *
+ClassTemplateSpecializationDecl::Create(ASTContext &Context, EmptyShell Empty) {
+ return
+ new (Context)ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
+}
+
void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
+ delete ExplicitInfo;
+
if (SpecializedPartialSpecialization *PartialSpec
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
C.Deallocate(PartialSpec);
@@ -508,6 +550,25 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L,
return Result;
}
+ClassTemplatePartialSpecializationDecl *
+ClassTemplatePartialSpecializationDecl::Create(ASTContext &Context,
+ EmptyShell Empty) {
+ return new (Context)ClassTemplatePartialSpecializationDecl();
+}
+
+void ClassTemplatePartialSpecializationDecl::
+initTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgInfos) {
+ assert(ArgsAsWritten == 0 && "ArgsAsWritten already set");
+ unsigned N = ArgInfos.size();
+ TemplateArgumentLoc *ClonedArgs
+ = new (getASTContext()) TemplateArgumentLoc[N];
+ for (unsigned I = 0; I != N; ++I)
+ ClonedArgs[I] = ArgInfos[I];
+
+ ArgsAsWritten = ClonedArgs;
+ NumArgsAsWritten = N;
+}
+
//===----------------------------------------------------------------------===//
// FriendTemplateDecl Implementation
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index c38cec3..6524a31 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -37,7 +37,7 @@ bool Expr::isKnownToHaveBooleanValue() const {
// If this value has _Bool type, it is obvious 0/1.
if (getType()->isBooleanType()) return true;
// If this is a non-scalar-integer type, we don't care enough to try.
- if (!getType()->isIntegralType()) return false;
+ if (!getType()->isIntegralOrEnumerationType()) return false;
if (const ParenExpr *PE = dyn_cast<ParenExpr>(this))
return PE->getSubExpr()->isKnownToHaveBooleanValue();
@@ -52,7 +52,9 @@ bool Expr::isKnownToHaveBooleanValue() const {
}
}
- if (const CastExpr *CE = dyn_cast<CastExpr>(this))
+ // Only look through implicit casts. If the user writes
+ // '(int) (a && b)' treat it as an arbitrary int.
+ if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(this))
return CE->getSubExpr()->isKnownToHaveBooleanValue();
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(this)) {
@@ -111,10 +113,14 @@ void ExplicitTemplateArgumentList::copyInto(
Info.addArgument(getTemplateArgs()[I]);
}
+std::size_t ExplicitTemplateArgumentList::sizeFor(unsigned NumTemplateArgs) {
+ return sizeof(ExplicitTemplateArgumentList) +
+ sizeof(TemplateArgumentLoc) * NumTemplateArgs;
+}
+
std::size_t ExplicitTemplateArgumentList::sizeFor(
const TemplateArgumentListInfo &Info) {
- return sizeof(ExplicitTemplateArgumentList) +
- sizeof(TemplateArgumentLoc) * Info.size();
+ return sizeFor(Info.size());
}
void DeclRefExpr::computeDependence() {
@@ -158,7 +164,7 @@ void DeclRefExpr::computeDependence() {
// (VD) - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent.
else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
- if (Var->getType()->isIntegralType() &&
+ if (Var->getType()->isIntegralOrEnumerationType() &&
Var->getType().getCVRQualifiers() == Qualifiers::Const) {
if (const Expr *Init = Var->getAnyInitializer())
if (Init->isValueDependent())
@@ -222,6 +228,19 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
TemplateArgs, T);
}
+DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier,
+ unsigned NumTemplateArgs) {
+ std::size_t Size = sizeof(DeclRefExpr);
+ if (HasQualifier)
+ Size += sizeof(NameQualifier);
+
+ if (NumTemplateArgs)
+ Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+
+ void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>());
+ return new (Mem) DeclRefExpr(EmptyShell());
+}
+
SourceRange DeclRefExpr::getSourceRange() const {
// FIXME: Does not handle multi-token names well, e.g., operator[].
SourceRange R(Loc);
@@ -557,7 +576,10 @@ QualType CallExpr::getCallReturnType() const {
CalleeType = FnTypePtr->getPointeeType();
else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>())
CalleeType = BPT->getPointeeType();
-
+ else if (const MemberPointerType *MPT
+ = CalleeType->getAs<MemberPointerType>())
+ CalleeType = MPT->getPointeeType();
+
const FunctionType *FnType = CalleeType->getAs<FunctionType>();
return FnType->getResultType();
}
@@ -662,6 +684,8 @@ const char *CastExpr::getCastKindName() const {
return "Unknown";
case CastExpr::CK_BitCast:
return "BitCast";
+ case CastExpr::CK_LValueBitCast:
+ return "LValueBitCast";
case CastExpr::CK_NoOp:
return "NoOp";
case CastExpr::CK_BaseToDerived:
@@ -968,7 +992,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
switch (BO->getOpcode()) {
default:
break;
- // Consider ',', '||', '&&' to have side effects if the LHS or RHS does.
+ // Consider the RHS of comma for side effects. LHS was checked by
+ // Sema::CheckCommaOperands.
case BinaryOperator::Comma:
// ((foo = <blah>), 0) is an idiom for hiding the result (and
// lvalue-ness) of an assignment written in a macro.
@@ -976,10 +1001,14 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
dyn_cast<IntegerLiteral>(BO->getRHS()->IgnoreParens()))
if (IE->getValue() == 0)
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:
- return (BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
- BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
+ if (!BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
+ !BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
+ return false;
+ break;
}
if (BO->isAssignmentOp())
return false;
@@ -1140,378 +1169,6 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
}
}
-/// DeclCanBeLvalue - Determine whether the given declaration can be
-/// an lvalue. This is a helper routine for isLvalue.
-static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) {
- // C++ [temp.param]p6:
- // A non-type non-reference template-parameter is not an lvalue.
- if (const NonTypeTemplateParmDecl *NTTParm
- = dyn_cast<NonTypeTemplateParmDecl>(Decl))
- return NTTParm->getType()->isReferenceType();
-
- return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) ||
- // C++ 3.10p2: An lvalue refers to an object or function.
- (Ctx.getLangOptions().CPlusPlus &&
- (isa<FunctionDecl>(Decl) || isa<FunctionTemplateDecl>(Decl)));
-}
-
-/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or an
-/// incomplete type other than void. Nonarray expressions that can be lvalues:
-/// - name, where name must be a variable
-/// - e[i]
-/// - (e), where e must be an lvalue
-/// - e.name, where e must be an lvalue
-/// - e->name
-/// - *e, the type of e cannot be a function type
-/// - string-constant
-/// - (__real__ e) and (__imag__ e) where e is an lvalue [GNU extension]
-/// - reference type [C++ [expr]]
-///
-Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
- assert(!TR->isReferenceType() && "Expressions can't have reference type.");
-
- isLvalueResult Res = isLvalueInternal(Ctx);
- if (Res != LV_Valid || Ctx.getLangOptions().CPlusPlus)
- return Res;
-
- // first, check the type (C99 6.3.2.1). Expressions with function
- // type in C are not lvalues, but they can be lvalues in C++.
- if (TR->isFunctionType() || TR == Ctx.OverloadTy)
- return LV_NotObjectType;
-
- // Allow qualified void which is an incomplete type other than void (yuck).
- if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
- return LV_IncompleteVoidType;
-
- return LV_Valid;
-}
-
-// Check whether the expression can be sanely treated like an l-value
-Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
- switch (getStmtClass()) {
- case ObjCIsaExprClass:
- case StringLiteralClass: // C99 6.5.1p4
- case ObjCEncodeExprClass: // @encode behaves like its string in every way.
- return LV_Valid;
- case ArraySubscriptExprClass: // C99 6.5.3p4 (e1[e2] == (*((e1)+(e2))))
- // For vectors, make sure base is an lvalue (i.e. not a function call).
- if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType())
- return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx);
- return LV_Valid;
- case DeclRefExprClass: { // C99 6.5.1p2
- const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl();
- if (DeclCanBeLvalue(RefdDecl, Ctx))
- return LV_Valid;
- break;
- }
- case BlockDeclRefExprClass: {
- const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(this);
- if (isa<VarDecl>(BDR->getDecl()))
- return LV_Valid;
- break;
- }
- case MemberExprClass: {
- const MemberExpr *m = cast<MemberExpr>(this);
- if (Ctx.getLangOptions().CPlusPlus) { // C++ [expr.ref]p4:
- NamedDecl *Member = m->getMemberDecl();
- // C++ [expr.ref]p4:
- // If E2 is declared to have type "reference to T", then E1.E2
- // is an lvalue.
- if (ValueDecl *Value = dyn_cast<ValueDecl>(Member))
- if (Value->getType()->isReferenceType())
- return LV_Valid;
-
- // -- If E2 is a static data member [...] then E1.E2 is an lvalue.
- if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord())
- return LV_Valid;
-
- // -- If E2 is a non-static data member [...]. If E1 is an
- // lvalue, then E1.E2 is an lvalue.
- if (isa<FieldDecl>(Member)) {
- if (m->isArrow())
- return LV_Valid;
- return m->getBase()->isLvalue(Ctx);
- }
-
- // -- If it refers to a static member function [...], then
- // E1.E2 is an lvalue.
- // -- Otherwise, if E1.E2 refers to a non-static member
- // function [...], then E1.E2 is not an lvalue.
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member))
- return Method->isStatic()? LV_Valid : LV_MemberFunction;
-
- // -- If E2 is a member enumerator [...], the expression E1.E2
- // is not an lvalue.
- if (isa<EnumConstantDecl>(Member))
- return LV_InvalidExpression;
-
- // Not an lvalue.
- return LV_InvalidExpression;
- }
-
- // C99 6.5.2.3p4
- if (m->isArrow())
- return LV_Valid;
- Expr *BaseExp = m->getBase();
- if (BaseExp->getStmtClass() == ObjCPropertyRefExprClass ||
- BaseExp->getStmtClass() == ObjCImplicitSetterGetterRefExprClass)
- return LV_SubObjCPropertySetting;
- return
- BaseExp->isLvalue(Ctx);
- }
- case UnaryOperatorClass:
- if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Deref)
- return LV_Valid; // C99 6.5.3p4
-
- if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Real ||
- cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Imag ||
- cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Extension)
- return cast<UnaryOperator>(this)->getSubExpr()->isLvalue(Ctx); // GNU.
-
- if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.pre.incr]p1
- (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::PreInc ||
- cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::PreDec))
- return LV_Valid;
- break;
- case ImplicitCastExprClass:
- if (cast<ImplicitCastExpr>(this)->isLvalueCast())
- return LV_Valid;
-
- // If this is a conversion to a class temporary, make a note of
- // that.
- if (Ctx.getLangOptions().CPlusPlus && getType()->isRecordType())
- return LV_ClassTemporary;
-
- break;
- case ParenExprClass: // C99 6.5.1p5
- return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx);
- case BinaryOperatorClass:
- case CompoundAssignOperatorClass: {
- const BinaryOperator *BinOp = cast<BinaryOperator>(this);
-
- if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.comma]p1
- BinOp->getOpcode() == BinaryOperator::Comma)
- return BinOp->getRHS()->isLvalue(Ctx);
-
- // C++ [expr.mptr.oper]p6
- // The result of a .* expression is an lvalue only if its first operand is
- // an lvalue and its second operand is a pointer to data member.
- if (BinOp->getOpcode() == BinaryOperator::PtrMemD &&
- !BinOp->getType()->isFunctionType())
- return BinOp->getLHS()->isLvalue(Ctx);
-
- // The result of an ->* expression is an lvalue only if its second operand
- // is a pointer to data member.
- if (BinOp->getOpcode() == BinaryOperator::PtrMemI &&
- !BinOp->getType()->isFunctionType()) {
- QualType Ty = BinOp->getRHS()->getType();
- if (Ty->isMemberPointerType() && !Ty->isMemberFunctionPointerType())
- return LV_Valid;
- }
-
- if (!BinOp->isAssignmentOp())
- return LV_InvalidExpression;
-
- if (Ctx.getLangOptions().CPlusPlus)
- // C++ [expr.ass]p1:
- // The result of an assignment operation [...] is an lvalue.
- return LV_Valid;
-
-
- // C99 6.5.16:
- // An assignment expression [...] is not an lvalue.
- return LV_InvalidExpression;
- }
- case CallExprClass:
- case CXXOperatorCallExprClass:
- case CXXMemberCallExprClass: {
- // C++0x [expr.call]p10
- // A function call is an lvalue if and only if the result type
- // is an lvalue reference.
- QualType ReturnType = cast<CallExpr>(this)->getCallReturnType();
- if (ReturnType->isLValueReferenceType())
- return LV_Valid;
-
- // If the function is returning a class temporary, make a note of
- // that.
- if (Ctx.getLangOptions().CPlusPlus && ReturnType->isRecordType())
- return LV_ClassTemporary;
-
- break;
- }
- case CompoundLiteralExprClass: // C99 6.5.2.5p5
- // FIXME: Is this what we want in C++?
- return LV_Valid;
- case ChooseExprClass:
- // __builtin_choose_expr is an lvalue if the selected operand is.
- return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx)->isLvalue(Ctx);
- case ExtVectorElementExprClass:
- if (cast<ExtVectorElementExpr>(this)->containsDuplicateElements())
- return LV_DuplicateVectorComponents;
- return LV_Valid;
- case ObjCIvarRefExprClass: // ObjC instance variables are lvalues.
- return LV_Valid;
- case ObjCPropertyRefExprClass: // FIXME: check if read-only property.
- return LV_Valid;
- case ObjCImplicitSetterGetterRefExprClass:
- // FIXME: check if read-only property.
- return LV_Valid;
- case PredefinedExprClass:
- return LV_Valid;
- case UnresolvedLookupExprClass:
- case UnresolvedMemberExprClass:
- return LV_Valid;
- case CXXDefaultArgExprClass:
- return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);
- case CStyleCastExprClass:
- case CXXFunctionalCastExprClass:
- case CXXStaticCastExprClass:
- case CXXDynamicCastExprClass:
- case CXXReinterpretCastExprClass:
- case CXXConstCastExprClass:
- // The result of an explicit cast is an lvalue if the type we are
- // casting to is an lvalue reference type. See C++ [expr.cast]p1,
- // C++ [expr.static.cast]p2, C++ [expr.dynamic.cast]p2,
- // C++ [expr.reinterpret.cast]p1, C++ [expr.const.cast]p1.
- if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()->
- isLValueReferenceType())
- return LV_Valid;
-
- // If this is a conversion to a class temporary, make a note of
- // that.
- if (Ctx.getLangOptions().CPlusPlus &&
- cast<ExplicitCastExpr>(this)->getTypeAsWritten()->isRecordType())
- return LV_ClassTemporary;
-
- break;
- case CXXTypeidExprClass:
- // C++ 5.2.8p1: The result of a typeid expression is an lvalue of ...
- return LV_Valid;
- case CXXBindTemporaryExprClass:
- return cast<CXXBindTemporaryExpr>(this)->getSubExpr()->
- isLvalueInternal(Ctx);
- case CXXBindReferenceExprClass:
- // Something that's bound to a reference is always an lvalue.
- return LV_Valid;
- case ConditionalOperatorClass: {
- // Complicated handling is only for C++.
- if (!Ctx.getLangOptions().CPlusPlus)
- return LV_InvalidExpression;
-
- // Sema should have taken care to ensure that a CXXTemporaryObjectExpr is
- // everywhere there's an object converted to an rvalue. Also, any other
- // casts should be wrapped by ImplicitCastExprs. There's just the special
- // case involving throws to work out.
- const ConditionalOperator *Cond = cast<ConditionalOperator>(this);
- Expr *True = Cond->getTrueExpr();
- Expr *False = Cond->getFalseExpr();
- // C++0x 5.16p2
- // If either the second or the third operand has type (cv) void, [...]
- // the result [...] is an rvalue.
- if (True->getType()->isVoidType() || False->getType()->isVoidType())
- return LV_InvalidExpression;
-
- // Both sides must be lvalues for the result to be an lvalue.
- if (True->isLvalue(Ctx) != LV_Valid || False->isLvalue(Ctx) != LV_Valid)
- return LV_InvalidExpression;
-
- // That's it.
- return LV_Valid;
- }
-
- case Expr::CXXExprWithTemporariesClass:
- return cast<CXXExprWithTemporaries>(this)->getSubExpr()->isLvalue(Ctx);
-
- case Expr::ObjCMessageExprClass:
- if (const ObjCMethodDecl *Method
- = cast<ObjCMessageExpr>(this)->getMethodDecl())
- if (Method->getResultType()->isLValueReferenceType())
- return LV_Valid;
- break;
-
- case Expr::CXXConstructExprClass:
- case Expr::CXXTemporaryObjectExprClass:
- case Expr::CXXZeroInitValueExprClass:
- return LV_ClassTemporary;
-
- default:
- break;
- }
- return LV_InvalidExpression;
-}
-
-/// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
-/// does not have an incomplete type, does not have a const-qualified type, and
-/// if it is a structure or union, does not have any member (including,
-/// recursively, any member or element of all contained aggregates or unions)
-/// with a const-qualified type.
-Expr::isModifiableLvalueResult
-Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
- isLvalueResult lvalResult = isLvalue(Ctx);
-
- switch (lvalResult) {
- case LV_Valid:
- // C++ 3.10p11: Functions cannot be modified, but pointers to
- // functions can be modifiable.
- if (Ctx.getLangOptions().CPlusPlus && TR->isFunctionType())
- return MLV_NotObjectType;
- break;
-
- case LV_NotObjectType: return MLV_NotObjectType;
- case LV_IncompleteVoidType: return MLV_IncompleteVoidType;
- case LV_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
- case LV_InvalidExpression:
- // If the top level is a C-style cast, and the subexpression is a valid
- // lvalue, then this is probably a use of the old-school "cast as lvalue"
- // GCC extension. We don't support it, but we want to produce good
- // diagnostics when it happens so that the user knows why.
- if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(IgnoreParens())) {
- if (CE->getSubExpr()->isLvalue(Ctx) == LV_Valid) {
- if (Loc)
- *Loc = CE->getLParenLoc();
- return MLV_LValueCast;
- }
- }
- return MLV_InvalidExpression;
- case LV_MemberFunction: return MLV_MemberFunction;
- case LV_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
- case LV_ClassTemporary:
- return MLV_ClassTemporary;
- }
-
- // The following is illegal:
- // void takeclosure(void (^C)(void));
- // void func() { int x = 1; takeclosure(^{ x = 7; }); }
- //
- if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(this)) {
- if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
- return MLV_NotBlockQualified;
- }
-
- // Assigning to an 'implicit' property?
- if (const ObjCImplicitSetterGetterRefExpr* Expr =
- dyn_cast<ObjCImplicitSetterGetterRefExpr>(this)) {
- if (Expr->getSetterMethod() == 0)
- return MLV_NoSetterProperty;
- }
-
- QualType CT = Ctx.getCanonicalType(getType());
-
- if (CT.isConstQualified())
- return MLV_ConstQualified;
- if (CT->isArrayType())
- return MLV_ArrayType;
- if (CT->isIncompleteType())
- return MLV_IncompleteType;
-
- if (const RecordType *r = CT->getAs<RecordType>()) {
- if (r->hasConstFields())
- return MLV_ConstQualified;
- }
-
- return MLV_Valid;
-}
-
/// isOBJCGCCandidate - Check if an expression is objc gc'able.
/// returns true, if it is; false otherwise.
bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
@@ -1596,7 +1253,7 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
if (CastExpr *P = dyn_cast<CastExpr>(E)) {
// We ignore integer <-> casts that are of the same width, ptr<->ptr and
- // ptr<->int casts of the same width. We also ignore all identify casts.
+ // ptr<->int casts of the same width. We also ignore all identity casts.
Expr *SE = P->getSubExpr();
if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) {
@@ -1604,8 +1261,10 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
continue;
}
- if ((E->getType()->isPointerType() || E->getType()->isIntegralType()) &&
- (SE->getType()->isPointerType() || SE->getType()->isIntegralType()) &&
+ if ((E->getType()->isPointerType() ||
+ E->getType()->isIntegralType(Ctx)) &&
+ (SE->getType()->isPointerType() ||
+ SE->getType()->isIntegralType(Ctx)) &&
Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) {
E = SE;
continue;
@@ -1795,7 +1454,7 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx,
// If the unthinkable happens, fall through to the safest alternative.
case NPC_ValueDependentIsNull:
- return isTypeDependent() || getType()->isIntegralType();
+ return isTypeDependent() || getType()->isIntegralType(Ctx);
case NPC_ValueDependentIsNotNull:
return false;
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
index d1a2b26..c2548ec 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -74,27 +74,27 @@ Stmt::child_iterator CXXDefaultArgExpr::child_end() {
return child_iterator();
}
-// CXXZeroInitValueExpr
-Stmt::child_iterator CXXZeroInitValueExpr::child_begin() {
+// CXXScalarValueInitExpr
+Stmt::child_iterator CXXScalarValueInitExpr::child_begin() {
return child_iterator();
}
-Stmt::child_iterator CXXZeroInitValueExpr::child_end() {
+Stmt::child_iterator CXXScalarValueInitExpr::child_end() {
return child_iterator();
}
// CXXNewExpr
CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
Expr **placementArgs, unsigned numPlaceArgs,
- bool parenTypeId, Expr *arraySize,
+ SourceRange TypeIdParens, Expr *arraySize,
CXXConstructorDecl *constructor, bool initializer,
Expr **constructorArgs, unsigned numConsArgs,
FunctionDecl *operatorDelete, QualType ty,
SourceLocation startLoc, SourceLocation endLoc)
: Expr(CXXNewExprClass, ty, ty->isDependentType(), ty->isDependentType()),
- GlobalNew(globalNew), ParenTypeId(parenTypeId),
+ GlobalNew(globalNew),
Initializer(initializer), SubExprs(0), OperatorNew(operatorNew),
OperatorDelete(operatorDelete), Constructor(constructor),
- StartLoc(startLoc), EndLoc(endLoc) {
+ TypeIdParens(TypeIdParens), StartLoc(startLoc), EndLoc(endLoc) {
AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs);
unsigned i = 0;
@@ -190,6 +190,18 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
return ULE;
}
+UnresolvedLookupExpr *
+UnresolvedLookupExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) {
+ std::size_t size = sizeof(UnresolvedLookupExpr);
+ if (NumTemplateArgs != 0)
+ size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+
+ void *Mem = C.Allocate(size, llvm::alignof<UnresolvedLookupExpr>());
+ UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
+ E->HasExplicitTemplateArgs = NumTemplateArgs != 0;
+ return E;
+}
+
OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T,
bool Dependent, NestedNameSpecifier *Qualifier,
SourceRange QRange, DeclarationName Name,
@@ -197,19 +209,28 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
: Expr(K, T, Dependent, Dependent),
- Results(0), NumResults(End - Begin), Name(Name), Qualifier(Qualifier),
+ Results(0), NumResults(0), Name(Name), Qualifier(Qualifier),
QualifierRange(QRange), NameLoc(NameLoc),
HasExplicitTemplateArgs(HasTemplateArgs)
{
+ initializeResults(C, Begin, End);
+}
+
+void OverloadExpr::initializeResults(ASTContext &C,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ assert(Results == 0 && "Results already initialized!");
+ NumResults = End - Begin;
if (NumResults) {
Results = static_cast<DeclAccessPair *>(
C.Allocate(sizeof(DeclAccessPair) * NumResults,
llvm::alignof<DeclAccessPair>()));
memcpy(Results, &*Begin.getIterator(),
- (End - Begin) * sizeof(DeclAccessPair));
+ NumResults * sizeof(DeclAccessPair));
}
}
+
bool OverloadExpr::ComputeDependence(UnresolvedSetIterator Begin,
UnresolvedSetIterator End,
const TemplateArgumentListInfo *Args) {
@@ -269,6 +290,19 @@ DependentScopeDeclRefExpr::Create(ASTContext &C,
return DRE;
}
+DependentScopeDeclRefExpr *
+DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
+ unsigned NumTemplateArgs) {
+ std::size_t size = sizeof(DependentScopeDeclRefExpr);
+ if (NumTemplateArgs)
+ size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ void *Mem = C.Allocate(size);
+
+ return new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
+ DeclarationName(),SourceLocation(),
+ NumTemplateArgs != 0);
+}
+
StmtIterator DependentScopeDeclRefExpr::child_begin() {
return child_iterator();
}
@@ -535,14 +569,6 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
}
}
-CXXConstructExpr::CXXConstructExpr(EmptyShell Empty, ASTContext &C,
- unsigned numargs)
- : Expr(CXXConstructExprClass, Empty), Args(0), NumArgs(numargs)
-{
- if (NumArgs)
- Args = new (C) Stmt*[NumArgs];
-}
-
void CXXConstructExpr::DoDestroy(ASTContext &C) {
DestroyChildren(C);
if (Args)
@@ -656,6 +682,14 @@ CXXUnresolvedConstructExpr::Create(ASTContext &C,
Args, NumArgs, RParenLoc);
}
+CXXUnresolvedConstructExpr *
+CXXUnresolvedConstructExpr::CreateEmpty(ASTContext &C, unsigned NumArgs) {
+ Stmt::EmptyShell Empty;
+ void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) +
+ sizeof(Expr *) * NumArgs);
+ return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs);
+}
+
Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() {
return child_iterator(reinterpret_cast<Stmt **>(this + 1));
}
@@ -714,6 +748,29 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C,
Member, MemberLoc, TemplateArgs);
}
+CXXDependentScopeMemberExpr *
+CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
+ unsigned NumTemplateArgs) {
+ if (NumTemplateArgs == 0)
+ return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(),
+ 0, SourceLocation(), 0,
+ SourceRange(), 0,
+ DeclarationName(),
+ SourceLocation());
+
+ std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
+ ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ void *Mem = C.Allocate(size, llvm::alignof<CXXDependentScopeMemberExpr>());
+ CXXDependentScopeMemberExpr *E
+ = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(),
+ 0, SourceLocation(), 0,
+ SourceRange(), 0,
+ DeclarationName(),
+ SourceLocation(), 0);
+ E->HasExplicitTemplateArgs = true;
+ return E;
+}
+
Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() {
return child_iterator(&Base);
}
@@ -770,6 +827,18 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
Member, MemberLoc, TemplateArgs, Begin, End);
}
+UnresolvedMemberExpr *
+UnresolvedMemberExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) {
+ std::size_t size = sizeof(UnresolvedMemberExpr);
+ if (NumTemplateArgs != 0)
+ size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+
+ void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>());
+ UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
+ E->HasExplicitTemplateArgs = NumTemplateArgs != 0;
+ return E;
+}
+
CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
// Unlike for UnresolvedLookupExpr, it is very easy to re-derive this.
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
new file mode 100644
index 0000000..60ac347
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
@@ -0,0 +1,471 @@
+//===--- ExprClassification.cpp - Expression AST Node Implementation ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Expr::classify.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ErrorHandling.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+using namespace clang;
+
+typedef Expr::Classification Cl;
+
+static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E);
+static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D);
+static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T);
+static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E);
+static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E);
+static Cl::Kinds ClassifyConditional(ASTContext &Ctx,
+ const ConditionalOperator *E);
+static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
+ Cl::Kinds Kind, SourceLocation &Loc);
+
+Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
+ assert(!TR->isReferenceType() && "Expressions can't have reference type.");
+
+ Cl::Kinds kind = ClassifyInternal(Ctx, this);
+ // C99 6.3.2.1: An lvalue is an expression with an object type or an
+ // incomplete type other than void.
+ if (!Ctx.getLangOptions().CPlusPlus) {
+ // Thus, no functions.
+ if (TR->isFunctionType() || TR == Ctx.OverloadTy)
+ kind = Cl::CL_Function;
+ // No void either, but qualified void is OK because it is "other than void".
+ else if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
+ kind = Cl::CL_Void;
+ }
+
+ Cl::ModifiableType modifiable = Cl::CM_Untested;
+ if (Loc)
+ modifiable = IsModifiable(Ctx, this, kind, *Loc);
+ return Classification(kind, modifiable);
+}
+
+static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
+ // This function takes the first stab at classifying expressions.
+ const LangOptions &Lang = Ctx.getLangOptions();
+
+ switch (E->getStmtClass()) {
+ // First come the expressions that are always lvalues, unconditionally.
+
+ case Expr::ObjCIsaExprClass:
+ // C++ [expr.prim.general]p1: A string literal is an lvalue.
+ case Expr::StringLiteralClass:
+ // @encode is equivalent to its string
+ case Expr::ObjCEncodeExprClass:
+ // __func__ and friends are too.
+ case Expr::PredefinedExprClass:
+ // Property references are lvalues
+ case Expr::ObjCPropertyRefExprClass:
+ case Expr::ObjCImplicitSetterGetterRefExprClass:
+ // C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of...
+ case Expr::CXXTypeidExprClass:
+ // Unresolved lookups get classified as lvalues.
+ // FIXME: Is this wise? Should they get their own kind?
+ case Expr::UnresolvedLookupExprClass:
+ case Expr::UnresolvedMemberExprClass:
+ // ObjC instance variables are lvalues
+ // FIXME: ObjC++0x might have different rules
+ case Expr::ObjCIvarRefExprClass:
+ // C99 6.5.2.5p5 says that compound literals are lvalues.
+ // FIXME: C++ might have a different opinion.
+ case Expr::CompoundLiteralExprClass:
+ return Cl::CL_LValue;
+
+ // Next come the complicated cases.
+
+ // C++ [expr.sub]p1: The result is an lvalue of type "T".
+ // However, subscripting vector types is more like member access.
+ case Expr::ArraySubscriptExprClass:
+ if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType())
+ return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase());
+ return Cl::CL_LValue;
+
+ // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
+ // function or variable and a prvalue otherwise.
+ case Expr::DeclRefExprClass:
+ return ClassifyDecl(Ctx, cast<DeclRefExpr>(E)->getDecl());
+ // We deal with names referenced from blocks the same way.
+ case Expr::BlockDeclRefExprClass:
+ return ClassifyDecl(Ctx, cast<BlockDeclRefExpr>(E)->getDecl());
+
+ // Member access is complex.
+ case Expr::MemberExprClass:
+ return ClassifyMemberExpr(Ctx, cast<MemberExpr>(E));
+
+ case Expr::UnaryOperatorClass:
+ switch (cast<UnaryOperator>(E)->getOpcode()) {
+ // 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:
+ return Cl::CL_LValue;
+
+ // GNU extensions, simply look through them.
+ case UnaryOperator::Real:
+ case UnaryOperator::Imag:
+ case UnaryOperator::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:
+ return Lang.CPlusPlus ? Cl::CL_LValue : Cl::CL_PRValue;
+
+ default:
+ return Cl::CL_PRValue;
+ }
+
+ // 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())
+ return Cl::CL_LValue;
+ return Lang.CPlusPlus && E->getType()->isRecordType() ?
+ Cl::CL_ClassTemporary : Cl::CL_PRValue;
+
+ // C++ [expr.prim.general]p4: The presence of parentheses does not affect
+ // whether the expression is an lvalue.
+ case Expr::ParenExprClass:
+ return ClassifyInternal(Ctx, cast<ParenExpr>(E)->getSubExpr());
+
+ case Expr::BinaryOperatorClass:
+ case Expr::CompoundAssignOperatorClass:
+ // C doesn't have any binary expressions that are lvalues.
+ if (Lang.CPlusPlus)
+ return ClassifyBinaryOp(Ctx, cast<BinaryOperator>(E));
+ return Cl::CL_PRValue;
+
+ case Expr::CallExprClass:
+ case Expr::CXXOperatorCallExprClass:
+ case Expr::CXXMemberCallExprClass:
+ return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType());
+
+ // __builtin_choose_expr is equivalent to the chosen expression.
+ case Expr::ChooseExprClass:
+ return ClassifyInternal(Ctx, cast<ChooseExpr>(E)->getChosenSubExpr(Ctx));
+
+ // Extended vector element access is an lvalue unless there are duplicates
+ // in the shuffle expression.
+ case Expr::ExtVectorElementExprClass:
+ return cast<ExtVectorElementExpr>(E)->containsDuplicateElements() ?
+ Cl::CL_DuplicateVectorComponents : Cl::CL_LValue;
+
+ // Simply look at the actual default argument.
+ case Expr::CXXDefaultArgExprClass:
+ return ClassifyInternal(Ctx, cast<CXXDefaultArgExpr>(E)->getExpr());
+
+ // Same idea for temporary binding.
+ case Expr::CXXBindTemporaryExprClass:
+ return ClassifyInternal(Ctx, cast<CXXBindTemporaryExpr>(E)->getSubExpr());
+
+ // And the temporary lifetime guard.
+ case Expr::CXXExprWithTemporariesClass:
+ return ClassifyInternal(Ctx, cast<CXXExprWithTemporaries>(E)->getSubExpr());
+
+ // Casts depend completely on the target type. All casts work the same.
+ case Expr::CStyleCastExprClass:
+ case Expr::CXXFunctionalCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXDynamicCastExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXConstCastExprClass:
+ // Only in C++ can casts be interesting at all.
+ if (!Lang.CPlusPlus) return Cl::CL_PRValue;
+ return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten());
+
+ case Expr::ConditionalOperatorClass:
+ // Once again, only C++ is interesting.
+ if (!Lang.CPlusPlus) return Cl::CL_PRValue;
+ return ClassifyConditional(Ctx, cast<ConditionalOperator>(E));
+
+ // ObjC message sends are effectively function calls, if the target function
+ // is known.
+ case Expr::ObjCMessageExprClass:
+ if (const ObjCMethodDecl *Method =
+ cast<ObjCMessageExpr>(E)->getMethodDecl()) {
+ return ClassifyUnnamed(Ctx, Method->getResultType());
+ }
+
+ // Some C++ expressions are always class temporaries.
+ case Expr::CXXConstructExprClass:
+ case Expr::CXXTemporaryObjectExprClass:
+ case Expr::CXXScalarValueInitExprClass:
+ return Cl::CL_ClassTemporary;
+
+ // Everything we haven't handled is a prvalue.
+ default:
+ return Cl::CL_PRValue;
+ }
+}
+
+/// ClassifyDecl - Return the classification of an expression referencing the
+/// given declaration.
+static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
+ // C++ [expr.prim.general]p6: The result is an lvalue if the entity is a
+ // function, variable, or data member and a prvalue otherwise.
+ // In C, functions are not lvalues.
+ // 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.
+ bool islvalue;
+ if (const NonTypeTemplateParmDecl *NTTParm =
+ dyn_cast<NonTypeTemplateParmDecl>(D))
+ islvalue = NTTParm->getType()->isReferenceType();
+ else
+ islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
+ (Ctx.getLangOptions().CPlusPlus &&
+ (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)));
+
+ return islvalue ? Cl::CL_LValue : Cl::CL_PRValue;
+}
+
+/// ClassifyUnnamed - Return the classification of an expression yielding an
+/// unnamed value of the given type. This applies in particular to function
+/// calls and casts.
+static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) {
+ // In C, function calls are always rvalues.
+ if (!Ctx.getLangOptions().CPlusPlus) return Cl::CL_PRValue;
+
+ // C++ [expr.call]p10: A function call is an lvalue if the result type is an
+ // lvalue reference type or an rvalue reference to function type, an xvalue
+ // if the result type is an rvalue refernence to object type, and a prvalue
+ // otherwise.
+ if (T->isLValueReferenceType())
+ return Cl::CL_LValue;
+ const RValueReferenceType *RV = T->getAs<RValueReferenceType>();
+ if (!RV) // Could still be a class temporary, though.
+ return T->isRecordType() ? Cl::CL_ClassTemporary : Cl::CL_PRValue;
+
+ return RV->getPointeeType()->isFunctionType() ? Cl::CL_LValue : Cl::CL_XValue;
+}
+
+static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) {
+ // Handle C first, it's easier.
+ if (!Ctx.getLangOptions().CPlusPlus) {
+ // C99 6.5.2.3p3
+ // For dot access, the expression is an lvalue if the first part is. For
+ // arrow access, it always is an lvalue.
+ if (E->isArrow())
+ return Cl::CL_LValue;
+ // ObjC property accesses are not lvalues, but get special treatment.
+ Expr *Base = E->getBase();
+ if (isa<ObjCPropertyRefExpr>(Base) ||
+ isa<ObjCImplicitSetterGetterRefExpr>(Base))
+ return Cl::CL_SubObjCPropertySetting;
+ return ClassifyInternal(Ctx, Base);
+ }
+
+ NamedDecl *Member = E->getMemberDecl();
+ // C++ [expr.ref]p3: E1->E2 is converted to the equivalent form (*(E1)).E2.
+ // C++ [expr.ref]p4: If E2 is declared to have type "reference to T", then
+ // E1.E2 is an lvalue.
+ if (ValueDecl *Value = dyn_cast<ValueDecl>(Member))
+ if (Value->getType()->isReferenceType())
+ return Cl::CL_LValue;
+
+ // Otherwise, one of the following rules applies.
+ // -- If E2 is a static member [...] then E1.E2 is an lvalue.
+ if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord())
+ return Cl::CL_LValue;
+
+ // -- If E2 is a non-static data member [...]. If E1 is an lvalue, then
+ // E1.E2 is an lvalue; if E1 is an xvalue, then E1.E2 is an xvalue;
+ // otherwise, it is a prvalue.
+ if (isa<FieldDecl>(Member)) {
+ // *E1 is an lvalue
+ if (E->isArrow())
+ return Cl::CL_LValue;
+ return ClassifyInternal(Ctx, E->getBase());
+ }
+
+ // -- If E2 is a [...] member function, [...]
+ // -- If it refers to a static member function [...], then E1.E2 is an
+ // lvalue; [...]
+ // -- Otherwise [...] E1.E2 is a prvalue.
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member))
+ return Method->isStatic() ? Cl::CL_LValue : Cl::CL_MemberFunction;
+
+ // -- If E2 is a member enumerator [...], the expression E1.E2 is a prvalue.
+ // So is everything else we haven't handled yet.
+ return Cl::CL_PRValue;
+}
+
+static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) {
+ assert(Ctx.getLangOptions().CPlusPlus &&
+ "This is only relevant for C++.");
+ // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand.
+ if (E->isAssignmentOp())
+ return Cl::CL_LValue;
+
+ // C++ [expr.comma]p1: the result is of the same value category as its right
+ // operand, [...].
+ if (E->getOpcode() == BinaryOperator::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)
+ 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)
+ return E->getType()->isFunctionType() ?
+ Cl::CL_MemberFunction : Cl::CL_LValue;
+
+ // All other binary operations are prvalues.
+ return Cl::CL_PRValue;
+}
+
+static Cl::Kinds ClassifyConditional(ASTContext &Ctx,
+ const ConditionalOperator *E) {
+ assert(Ctx.getLangOptions().CPlusPlus &&
+ "This is only relevant for C++.");
+
+ Expr *True = E->getTrueExpr();
+ Expr *False = E->getFalseExpr();
+ // C++ [expr.cond]p2
+ // If either the second or the third operand has type (cv) void, [...]
+ // the result [...] is a prvalue.
+ if (True->getType()->isVoidType() || False->getType()->isVoidType())
+ return Cl::CL_PRValue;
+
+ // Note that at this point, we have already performed all conversions
+ // according to [expr.cond]p3.
+ // C++ [expr.cond]p4: If the second and third operands are glvalues of the
+ // same value category [...], the result is of that [...] value category.
+ // C++ [expr.cond]p5: Otherwise, the result is a prvalue.
+ Cl::Kinds LCl = ClassifyInternal(Ctx, True),
+ RCl = ClassifyInternal(Ctx, False);
+ return LCl == RCl ? LCl : Cl::CL_PRValue;
+}
+
+static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
+ Cl::Kinds Kind, SourceLocation &Loc) {
+ // As a general rule, we only care about lvalues. But there are some rvalues
+ // for which we want to generate special results.
+ if (Kind == Cl::CL_PRValue) {
+ // For the sake of better diagnostics, we want to specifically recognize
+ // use of the GCC cast-as-lvalue extension.
+ if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E->IgnoreParens())){
+ if (CE->getSubExpr()->Classify(Ctx).isLValue()) {
+ Loc = CE->getLParenLoc();
+ return Cl::CM_LValueCast;
+ }
+ }
+ }
+ if (Kind != Cl::CL_LValue)
+ return Cl::CM_RValue;
+
+ // This is the lvalue case.
+ // Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6)
+ if (Ctx.getLangOptions().CPlusPlus && E->getType()->isFunctionType())
+ return Cl::CM_Function;
+
+ // You cannot assign to a variable outside a block from within the block if
+ // it is not marked __block, e.g.
+ // void takeclosure(void (^C)(void));
+ // void func() { int x = 1; takeclosure(^{ x = 7; }); }
+ if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E)) {
+ if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
+ return Cl::CM_NotBlockQualified;
+ }
+
+ // Assignment to a property in ObjC is an implicit setter access. But a
+ // setter might not exist.
+ if (const ObjCImplicitSetterGetterRefExpr *Expr =
+ dyn_cast<ObjCImplicitSetterGetterRefExpr>(E)) {
+ if (Expr->getSetterMethod() == 0)
+ return Cl::CM_NoSetterProperty;
+ }
+
+ CanQualType CT = Ctx.getCanonicalType(E->getType());
+ // Const stuff is obviously not modifiable.
+ if (CT.isConstQualified())
+ return Cl::CM_ConstQualified;
+ // Arrays are not modifiable, only their elements are.
+ if (CT->isArrayType())
+ return Cl::CM_ArrayType;
+ // Incomplete types are not modifiable.
+ if (CT->isIncompleteType())
+ return Cl::CM_IncompleteType;
+
+ // Records with any const fields (recursively) are not modifiable.
+ if (const RecordType *R = CT->getAs<RecordType>()) {
+ assert(!Ctx.getLangOptions().CPlusPlus &&
+ "C++ struct assignment should be resolved by the "
+ "copy assignment operator.");
+ if (R->hasConstFields())
+ return Cl::CM_ConstQualified;
+ }
+
+ return Cl::CM_Modifiable;
+}
+
+Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
+ Classification VC = Classify(Ctx);
+ switch (VC.getKind()) {
+ case Cl::CL_LValue: return LV_Valid;
+ case Cl::CL_XValue: return LV_InvalidExpression;
+ case Cl::CL_Function: return LV_NotObjectType;
+ case Cl::CL_Void: return LV_IncompleteVoidType;
+ case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents;
+ case Cl::CL_MemberFunction: return LV_MemberFunction;
+ case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting;
+ case Cl::CL_ClassTemporary: return LV_ClassTemporary;
+ case Cl::CL_PRValue: return LV_InvalidExpression;
+ }
+ llvm_unreachable("Unhandled kind");
+}
+
+Expr::isModifiableLvalueResult
+Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
+ SourceLocation dummy;
+ Classification VC = ClassifyModifiable(Ctx, Loc ? *Loc : dummy);
+ switch (VC.getKind()) {
+ case Cl::CL_LValue: break;
+ case Cl::CL_XValue: return MLV_InvalidExpression;
+ case Cl::CL_Function: return MLV_NotObjectType;
+ case Cl::CL_Void: return MLV_IncompleteVoidType;
+ case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
+ case Cl::CL_MemberFunction: return MLV_MemberFunction;
+ case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
+ case Cl::CL_ClassTemporary: return MLV_ClassTemporary;
+ case Cl::CL_PRValue:
+ return VC.getModifiable() == Cl::CM_LValueCast ?
+ MLV_LValueCast : MLV_InvalidExpression;
+ }
+ assert(VC.getKind() == Cl::CL_LValue && "Unhandled kind");
+ switch (VC.getModifiable()) {
+ case Cl::CM_Untested: llvm_unreachable("Did not test modifiability");
+ case Cl::CM_Modifiable: return MLV_Valid;
+ case Cl::CM_RValue: llvm_unreachable("CM_RValue and CL_LValue don't match");
+ case Cl::CM_Function: return MLV_NotObjectType;
+ case Cl::CM_LValueCast:
+ llvm_unreachable("CM_LValueCast and CL_LValue don't match");
+ case Cl::CM_NotBlockQualified: return MLV_NotBlockQualified;
+ case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty;
+ case Cl::CM_ConstQualified: return MLV_ConstQualified;
+ case Cl::CM_ArrayType: return MLV_ArrayType;
+ case Cl::CM_IncompleteType: return MLV_IncompleteType;
+ }
+ llvm_unreachable("Unhandled modifiable type");
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index dc61401..3c97420 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -157,7 +157,7 @@ static bool EvalPointerValueAsBool(LValue& Value, bool& Result) {
static bool HandleConversionToBool(const Expr* E, bool& Result,
EvalInfo &Info) {
- if (E->getType()->isIntegralType()) {
+ if (E->getType()->isIntegralOrEnumerationType()) {
APSInt IntResult;
if (!EvaluateInteger(E, IntResult, Info))
return false;
@@ -542,7 +542,7 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
SubExpr->getType()->isBlockPointerType())
return Visit(SubExpr);
- if (SubExpr->getType()->isIntegralType()) {
+ if (SubExpr->getType()->isIntegralOrEnumerationType()) {
APValue Value;
if (!EvaluateIntegerOrLValue(SubExpr, Value, Info))
break;
@@ -563,6 +563,7 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
case CastExpr::CK_NoOp:
case CastExpr::CK_BitCast:
+ case CastExpr::CK_LValueBitCast:
case CastExpr::CK_AnyPointerToObjCPointerCast:
case CastExpr::CK_AnyPointerToBlockPointerCast:
return Visit(SubExpr);
@@ -746,25 +747,46 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
QualType EltTy = VT->getElementType();
llvm::SmallVector<APValue, 4> Elements;
- for (unsigned i = 0; i < NumElements; i++) {
+ // If a vector is initialized with a single element, that value
+ // becomes every element of the vector, not just the first.
+ // This is the behavior described in the IBM AltiVec documentation.
+ if (NumInits == 1) {
+ APValue InitValue;
if (EltTy->isIntegerType()) {
llvm::APSInt sInt(32);
- if (i < NumInits) {
- if (!EvaluateInteger(E->getInit(i), sInt, Info))
- return APValue();
- } else {
- sInt = Info.Ctx.MakeIntValue(0, EltTy);
- }
- Elements.push_back(APValue(sInt));
+ if (!EvaluateInteger(E->getInit(0), sInt, Info))
+ return APValue();
+ InitValue = APValue(sInt);
} else {
llvm::APFloat f(0.0);
- if (i < NumInits) {
- if (!EvaluateFloat(E->getInit(i), f, Info))
- return APValue();
+ if (!EvaluateFloat(E->getInit(0), f, Info))
+ return APValue();
+ InitValue = APValue(f);
+ }
+ for (unsigned i = 0; i < NumElements; i++) {
+ Elements.push_back(InitValue);
+ }
+ } else {
+ for (unsigned i = 0; i < NumElements; i++) {
+ if (EltTy->isIntegerType()) {
+ llvm::APSInt sInt(32);
+ if (i < NumInits) {
+ if (!EvaluateInteger(E->getInit(i), sInt, Info))
+ return APValue();
+ } else {
+ sInt = Info.Ctx.MakeIntValue(0, EltTy);
+ }
+ Elements.push_back(APValue(sInt));
} else {
- f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy));
+ llvm::APFloat f(0.0);
+ if (i < NumInits) {
+ if (!EvaluateFloat(E->getInit(i), f, Info))
+ return APValue();
+ } else {
+ f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy));
+ }
+ Elements.push_back(APValue(f));
}
- Elements.push_back(APValue(f));
}
}
return APValue(&Elements[0], Elements.size());
@@ -818,7 +840,8 @@ public:
: Info(info), Result(result) {}
bool Success(const llvm::APSInt &SI, const Expr *E) {
- assert(E->getType()->isIntegralType() && "Invalid evaluation result.");
+ assert(E->getType()->isIntegralOrEnumerationType() &&
+ "Invalid evaluation result.");
assert(SI.isSigned() == E->getType()->isSignedIntegerType() &&
"Invalid evaluation result.");
assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
@@ -828,7 +851,8 @@ public:
}
bool Success(const llvm::APInt &I, const Expr *E) {
- assert(E->getType()->isIntegralType() && "Invalid evaluation result.");
+ assert(E->getType()->isIntegralOrEnumerationType() &&
+ "Invalid evaluation result.");
assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
"Invalid evaluation result.");
Result = APValue(APSInt(I));
@@ -837,7 +861,8 @@ public:
}
bool Success(uint64_t Value, const Expr *E) {
- assert(E->getType()->isIntegralType() && "Invalid evaluation result.");
+ assert(E->getType()->isIntegralOrEnumerationType() &&
+ "Invalid evaluation result.");
Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType()));
return true;
}
@@ -914,7 +939,7 @@ public:
return Success(0, E);
}
- bool VisitCXXZeroInitValueExpr(const CXXZeroInitValueExpr *E) {
+ bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
return Success(0, E);
}
@@ -943,12 +968,12 @@ private:
} // end anonymous namespace
static bool EvaluateIntegerOrLValue(const Expr* E, APValue &Result, EvalInfo &Info) {
- assert(E->getType()->isIntegralType());
+ assert(E->getType()->isIntegralOrEnumerationType());
return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
}
static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
- assert(E->getType()->isIntegralType());
+ assert(E->getType()->isIntegralOrEnumerationType());
APValue Val;
if (!EvaluateIntegerOrLValue(E, Val, Info) || !Val.isInt())
@@ -1314,8 +1339,8 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
return Success(Result, E);
}
}
- if (!LHSTy->isIntegralType() ||
- !RHSTy->isIntegralType()) {
+ if (!LHSTy->isIntegralOrEnumerationType() ||
+ !RHSTy->isIntegralOrEnumerationType()) {
// We can't continue from here for non-integral types, and they
// could potentially confuse the following operations.
return false;
@@ -1570,7 +1595,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
}
// Only handle integral operations...
- if (!E->getSubExpr()->getType()->isIntegralType())
+ if (!E->getSubExpr()->getType()->isIntegralOrEnumerationType())
return false;
// Get the operand value into 'Result'.
@@ -1613,7 +1638,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
}
// Handle simple integer->integer casts.
- if (SrcType->isIntegralType()) {
+ if (SrcType->isIntegralOrEnumerationType()) {
if (!Visit(SubExpr))
return false;
@@ -1732,7 +1757,7 @@ public:
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitFloatingLiteral(const FloatingLiteral *E);
bool VisitCastExpr(CastExpr *E);
- bool VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
+ bool VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
bool VisitConditionalOperator(ConditionalOperator *E);
bool VisitChooseExpr(const ChooseExpr *E)
@@ -1908,7 +1933,7 @@ bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) {
bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) {
Expr* SubExpr = E->getSubExpr();
- if (SubExpr->getType()->isIntegralType()) {
+ if (SubExpr->getType()->isIntegralOrEnumerationType()) {
APSInt IntResult;
if (!EvaluateInteger(SubExpr, IntResult, Info))
return false;
@@ -1928,7 +1953,7 @@ bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) {
return false;
}
-bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType()));
return true;
}
@@ -2186,6 +2211,8 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const {
} else if (E->getType()->isIntegerType()) {
if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(const_cast<Expr*>(E)))
return false;
+ if (Result.Val.isLValue() && !IsGlobalLValue(Result.Val.getLValueBase()))
+ return false;
} else if (E->getType()->hasPointerRepresentation()) {
LValue LV;
if (!EvaluatePointer(E, LV, Info))
@@ -2316,7 +2343,7 @@ static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) {
static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
assert(!E->isValueDependent() && "Should not see value dependent exprs!");
- if (!E->getType()->isIntegralType()) {
+ if (!E->getType()->isIntegralOrEnumerationType()) {
return ICEDiag(2, E->getLocStart());
}
@@ -2384,7 +2411,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::IntegerLiteralClass:
case Expr::CharacterLiteralClass:
case Expr::CXXBoolLiteralExprClass:
- case Expr::CXXZeroInitValueExprClass:
+ case Expr::CXXScalarValueInitExprClass:
case Expr::TypesCompatibleExprClass:
case Expr::UnaryTypeTraitExprClass:
return NoDiag();
@@ -2579,7 +2606,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXConstCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
- if (SubExpr->getType()->isIntegralType())
+ if (SubExpr->getType()->isIntegralOrEnumerationType())
return CheckICE(SubExpr, Ctx);
if (isa<FloatingLiteral>(SubExpr->IgnoreParens()))
return NoDiag();
diff --git a/contrib/llvm/tools/clang/lib/AST/Makefile b/contrib/llvm/tools/clang/lib/AST/Makefile
index ede2577..7a1672b 100644
--- a/contrib/llvm/tools/clang/lib/AST/Makefile
+++ b/contrib/llvm/tools/clang/lib/AST/Makefile
@@ -11,11 +11,9 @@
#
##===----------------------------------------------------------------------===##
-LEVEL = ../../../..
+CLANG_LEVEL := ../..
LIBRARYNAME := clangAST
BUILD_ARCHIVE = 1
-CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
-
-include $(LEVEL)/Makefile.common
+include $(CLANG_LEVEL)/Makefile
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
index 983a287..88d71ce 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -23,6 +23,35 @@ using namespace clang;
namespace {
+/// BaseSubobjectInfo - Represents a single base subobject in a complete class.
+/// For a class hierarchy like
+///
+/// class A { };
+/// class B : A { };
+/// class C : A, B { };
+///
+/// The BaseSubobjectInfo graph for C will have three BaseSubobjectInfo
+/// instances, one for B and two for A.
+///
+/// If a base is virtual, it will only have one BaseSubobjectInfo allocated.
+struct BaseSubobjectInfo {
+ /// Class - The class for this base info.
+ const CXXRecordDecl *Class;
+
+ /// IsVirtual - Whether the BaseInfo represents a virtual base or not.
+ bool IsVirtual;
+
+ /// Bases - Information about the base subobjects.
+ llvm::SmallVector<BaseSubobjectInfo*, 4> Bases;
+
+ /// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base
+ /// of this base info (if one exists).
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo;
+
+ // FIXME: Document.
+ const BaseSubobjectInfo *Derived;
+};
+
/// EmptySubobjectMap - Keeps track of which empty subobjects exist at different
/// offsets while laying out a C++ class.
class EmptySubobjectMap {
@@ -36,30 +65,41 @@ class EmptySubobjectMap {
typedef llvm::DenseMap<uint64_t, ClassVectorTy> EmptyClassOffsetsMapTy;
EmptyClassOffsetsMapTy EmptyClassOffsets;
+ /// MaxEmptyClassOffset - The highest offset known to contain an empty
+ /// base subobject.
+ uint64_t MaxEmptyClassOffset;
+
/// ComputeEmptySubobjectSizes - Compute the size of the largest base or
/// member subobject that is empty.
void ComputeEmptySubobjectSizes();
+
+ bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
+ uint64_t Offset) const;
- struct BaseInfo {
- const CXXRecordDecl *Class;
- bool IsVirtual;
-
- const CXXRecordDecl *PrimaryVirtualBase;
-
- llvm::SmallVector<BaseInfo*, 4> Bases;
- const BaseInfo *Derived;
- };
+ void AddSubobjectAtOffset(const CXXRecordDecl *RD, uint64_t Offset);
- llvm::DenseMap<const CXXRecordDecl *, BaseInfo *> VirtualBaseInfo;
- llvm::DenseMap<const CXXRecordDecl *, BaseInfo *> NonVirtualBaseInfo;
+ bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
+ uint64_t Offset);
+ void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
+ uint64_t Offset, bool PlacingEmptyBase);
- BaseInfo *ComputeBaseInfo(const CXXRecordDecl *RD, bool IsVirtual,
- const BaseInfo *Derived);
- void ComputeBaseInfo();
+ bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ uint64_t Offset) const;
+ bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
+ uint64_t Offset) const;
- bool CanPlaceBaseSubobjectAtOffset(const BaseInfo *Info, uint64_t Offset);
- void UpdateEmptyBaseSubobjects(const BaseInfo *Info, uint64_t Offset);
+ void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ uint64_t Offset);
+ void UpdateEmptyFieldSubobjects(const FieldDecl *FD, uint64_t Offset);
+ /// AnyEmptySubobjectsBeyondOffset - Returns whether there are any empty
+ /// subobjects beyond the given offset.
+ bool AnyEmptySubobjectsBeyondOffset(uint64_t Offset) const {
+ return Offset <= MaxEmptyClassOffset;
+ }
+
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
@@ -67,18 +107,21 @@ public:
uint64_t SizeOfLargestEmptySubobject;
EmptySubobjectMap(ASTContext &Context, const CXXRecordDecl *Class)
- : Context(Context), Class(Class), SizeOfLargestEmptySubobject(0) {
+ : Context(Context), Class(Class), MaxEmptyClassOffset(0),
+ SizeOfLargestEmptySubobject(0) {
ComputeEmptySubobjectSizes();
-
- ComputeBaseInfo();
}
/// CanPlaceBaseAtOffset - Return whether the given base class can be placed
/// at the given offset.
/// Returns false if placing the record will result in two components
/// (direct or indirect) of the same type having the same offset.
- bool CanPlaceBaseAtOffset(const CXXRecordDecl *RD, bool BaseIsVirtual,
+ bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
uint64_t Offset);
+
+ /// CanPlaceFieldAtOffset - Return whether a field can be placed at the given
+ /// offset.
+ bool CanPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset);
};
void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
@@ -130,93 +173,67 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
}
}
-EmptySubobjectMap::BaseInfo *
-EmptySubobjectMap::ComputeBaseInfo(const CXXRecordDecl *RD, bool IsVirtual,
- const BaseInfo *Derived) {
- BaseInfo *Info;
-
- if (IsVirtual) {
- BaseInfo *&InfoSlot = VirtualBaseInfo[RD];
- if (InfoSlot) {
- assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");
- return InfoSlot;
- }
+bool
+EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
+ uint64_t Offset) const {
+ // We only need to check empty bases.
+ if (!RD->isEmpty())
+ return true;
- InfoSlot = new (Context) BaseInfo;
- Info = InfoSlot;
- } else {
- Info = new (Context) BaseInfo;
- }
-
- Info->Class = RD;
- Info->IsVirtual = IsVirtual;
- Info->Derived = Derived;
- Info->PrimaryVirtualBase = 0;
+ EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
+ if (I == EmptyClassOffsets.end())
+ return true;
- if (RD->getNumVBases()) {
- // Check if this class has a primary virtual base.
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- if (Layout.getPrimaryBaseWasVirtual()) {
- Info->PrimaryVirtualBase = Layout.getPrimaryBase();
- assert(Info->PrimaryVirtualBase &&
- "Didn't have a primary virtual base!");
- }
- }
+ const ClassVectorTy& Classes = I->second;
+ if (std::find(Classes.begin(), Classes.end(), RD) == Classes.end())
+ return true;
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- bool IsVirtual = I->isVirtual();
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- Info->Bases.push_back(ComputeBaseInfo(BaseDecl, IsVirtual, Info));
- }
-
- return Info;
+ // There is already an empty class of the same type at this offset.
+ return false;
}
+
+void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
+ uint64_t Offset) {
+ // We only care about empty bases.
+ if (!RD->isEmpty())
+ return;
-void EmptySubobjectMap::ComputeBaseInfo() {
- for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
- E = Class->bases_end(); I != E; ++I) {
- bool IsVirtual = I->isVirtual();
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- BaseInfo *Info = ComputeBaseInfo(BaseDecl, IsVirtual, /*Derived=*/0);
- if (IsVirtual) {
- // ComputeBaseInfo has already added this base for us.
- continue;
- }
+ ClassVectorTy& Classes = EmptyClassOffsets[Offset];
+ assert(std::find(Classes.begin(), Classes.end(), RD) == Classes.end() &&
+ "Duplicate empty class detected!");
- // Add the base info to the map of non-virtual bases.
- assert(!NonVirtualBaseInfo.count(BaseDecl) &&
- "Non-virtual base already exists!");
- NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
- }
+ Classes.push_back(RD);
+
+ // Update the empty class offset.
+ MaxEmptyClassOffset = std::max(MaxEmptyClassOffset, Offset);
}
bool
-EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseInfo *Info,
+EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
uint64_t Offset) {
+ // We don't have to keep looking past the maximum offset that's known to
+ // contain an empty class.
+ if (!AnyEmptySubobjectsBeyondOffset(Offset))
+ return true;
+
+ if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
+ return false;
+
// Traverse all non-virtual bases.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) {
- BaseInfo* Base = Info->Bases[I];
+ BaseSubobjectInfo* Base = Info->Bases[I];
if (Base->IsVirtual)
continue;
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
return false;
}
- if (Info->PrimaryVirtualBase) {
- BaseInfo *PrimaryVirtualBaseInfo =
- VirtualBaseInfo.lookup(Info->PrimaryVirtualBase);
- assert(PrimaryVirtualBaseInfo && "Didn't find base info!");
+ if (Info->PrimaryVirtualBaseInfo) {
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
if (Info == PrimaryVirtualBaseInfo->Derived) {
if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
@@ -224,62 +241,277 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseInfo *Info,
}
}
- // FIXME: Member variables.
+ // Traverse all member variables.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
+ E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+
+ uint64_t FieldOffset = Offset + Layout.getFieldOffset(FieldNo);
+ if (!CanPlaceFieldSubobjectAtOffset(FD, FieldOffset))
+ return false;
+ }
+
return true;
}
-void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseInfo *Info,
- uint64_t Offset) {
- if (Info->Class->isEmpty()) {
- // FIXME: Record that there is an empty class at this offset.
+void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
+ uint64_t Offset,
+ bool PlacingEmptyBase) {
+ if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
+ // We know that the only empty subobjects that can conflict with empty
+ // subobject of non-empty bases, are empty bases that can be placed at
+ // offset zero. Because of this, we only need to keep track of empty base
+ // subobjects with offsets less than the size of the largest empty
+ // subobject for our class.
+ return;
}
-
+
+ AddSubobjectAtOffset(Info->Class, Offset);
+
// Traverse all non-virtual bases.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) {
- BaseInfo* Base = Info->Bases[I];
+ BaseSubobjectInfo* Base = Info->Bases[I];
if (Base->IsVirtual)
continue;
-
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
+
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
-
- UpdateEmptyBaseSubobjects(Base, BaseOffset);
+ UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
}
- if (Info->PrimaryVirtualBase) {
- BaseInfo *PrimaryVirtualBaseInfo =
- VirtualBaseInfo.lookup(Info->PrimaryVirtualBase);
- assert(PrimaryVirtualBaseInfo && "Didn't find base info!");
+ if (Info->PrimaryVirtualBaseInfo) {
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
if (Info == PrimaryVirtualBaseInfo->Derived)
- UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset);
+ UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
+ PlacingEmptyBase);
+ }
+
+ // Traverse all member variables.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
+ E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+
+ uint64_t FieldOffset = Offset + Layout.getFieldOffset(FieldNo);
+ UpdateEmptyFieldSubobjects(FD, FieldOffset);
}
-
- // FIXME: Member variables.
}
-bool EmptySubobjectMap::CanPlaceBaseAtOffset(const CXXRecordDecl *RD,
- bool BaseIsVirtual,
+bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
uint64_t Offset) {
// If we know this class doesn't have any empty subobjects we don't need to
// bother checking.
if (!SizeOfLargestEmptySubobject)
return true;
- BaseInfo *Info;
+ if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
+ return false;
+
+ // We are able to place the base at this offset. Make sure to update the
+ // empty base subobject map.
+ UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
+ return true;
+}
+
+bool
+EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ uint64_t Offset) const {
+ // We don't have to keep looking past the maximum offset that's known to
+ // contain an empty class.
+ if (!AnyEmptySubobjectsBeyondOffset(Offset))
+ return true;
+
+ if (!CanPlaceSubobjectAtOffset(RD, Offset))
+ return false;
- if (BaseIsVirtual)
- Info = VirtualBaseInfo.lookup(RD);
- else
- Info = NonVirtualBaseInfo.lookup(RD);
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Traverse all non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
+ if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
+ return false;
+ }
+
+ if (RD == Class) {
+ // This is the most derived class, traverse virtual bases as well.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *VBaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ uint64_t VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
+ if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
+ return false;
+ }
+ }
+
+ // Traverse all member variables.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+
+ uint64_t FieldOffset = Offset + Layout.getFieldOffset(FieldNo);
+
+ if (!CanPlaceFieldSubobjectAtOffset(FD, FieldOffset))
+ return false;
+ }
+
+ return true;
+}
+
+bool EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
+ uint64_t Offset) const {
+ // We don't have to keep looking past the maximum offset that's known to
+ // contain an empty class.
+ if (!AnyEmptySubobjectsBeyondOffset(Offset))
+ return true;
- if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
+ QualType T = FD->getType();
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
+ }
+
+ // If we have an array type we need to look at every element.
+ if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
+ QualType ElemTy = Context.getBaseElementType(AT);
+ const RecordType *RT = ElemTy->getAs<RecordType>();
+ if (!RT)
+ return true;
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ uint64_t NumElements = Context.getConstantArrayElementCount(AT);
+ uint64_t ElementOffset = Offset;
+ for (uint64_t I = 0; I != NumElements; ++I) {
+ // We don't have to keep looking past the maximum offset that's known to
+ // contain an empty class.
+ if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
+ return true;
+
+ if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
+ return false;
+
+ ElementOffset += Layout.getSize();
+ }
+ }
+
+ return true;
+}
+
+bool
+EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) {
+ if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
return false;
- UpdateEmptyBaseSubobjects(Info, Offset);
+ // We are able to place the member variable at this offset.
+ // Make sure to update the empty base subobject map.
+ UpdateEmptyFieldSubobjects(FD, Offset);
return true;
}
+void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ uint64_t Offset) {
+ // We know that the only empty subobjects that can conflict with empty
+ // field subobjects are subobjects of empty bases that can be placed at offset
+ // zero. Because of this, we only need to keep track of empty field
+ // subobjects with offsets less than the size of the largest empty
+ // subobject for our class.
+ if (Offset >= SizeOfLargestEmptySubobject)
+ return;
+
+ AddSubobjectAtOffset(RD, Offset);
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Traverse all non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
+ UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset);
+ }
+
+ if (RD == Class) {
+ // This is the most derived class, traverse virtual bases as well.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *VBaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ uint64_t VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
+ UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
+ }
+ }
+
+ // Traverse all member variables.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+
+ uint64_t FieldOffset = Offset + Layout.getFieldOffset(FieldNo);
+
+ UpdateEmptyFieldSubobjects(FD, FieldOffset);
+ }
+}
+
+void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD,
+ uint64_t Offset) {
+ QualType T = FD->getType();
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ UpdateEmptyFieldSubobjects(RD, RD, Offset);
+ return;
+ }
+
+ // If we have an array type we need to update every element.
+ if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
+ QualType ElemTy = Context.getBaseElementType(AT);
+ const RecordType *RT = ElemTy->getAs<RecordType>();
+ if (!RT)
+ return;
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ uint64_t NumElements = Context.getConstantArrayElementCount(AT);
+ uint64_t ElementOffset = Offset;
+
+ for (uint64_t I = 0; I != NumElements; ++I) {
+ // We know that the only empty subobjects that can conflict with empty
+ // field subobjects are subobjects of empty bases that can be placed at
+ // offset zero. Because of this, we only need to keep track of empty field
+ // subobjects with offsets less than the size of the largest empty
+ // subobject for our class.
+ if (ElementOffset >= SizeOfLargestEmptySubobject)
+ return;
+
+ UpdateEmptyFieldSubobjects(RD, RD, ElementOffset);
+ ElementOffset += Layout.getSize();
+ }
+ }
+}
+
class RecordLayoutBuilder {
// FIXME: Remove this and make the appropriate fields public.
friend class clang::ASTContext;
@@ -346,10 +578,6 @@ class RecordLayoutBuilder {
/// avoid visiting virtual bases more than once.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
- /// EmptyClassOffsets - A map from offsets to empty record decls.
- typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
- EmptyClassOffsetsTy EmptyClassOffsets;
-
RecordLayoutBuilder(ASTContext &Context, EmptySubobjectMap *EmptySubobjects)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(8),
Packed(false), IsUnion(false), IsMac68kAlign(false),
@@ -366,9 +594,29 @@ class RecordLayoutBuilder {
void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize);
void LayoutBitField(const FieldDecl *D);
- /// ComputeEmptySubobjectSizes - Compute the size of the largest base or
- /// member subobject that is empty.
- void ComputeEmptySubobjectSizes(const CXXRecordDecl *RD);
+ /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects.
+ llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
+ BaseSubobjectInfoMapTy;
+
+ /// VirtualBaseInfo - Map from all the (direct or indirect) virtual bases
+ /// of the class we're laying out to their base subobject info.
+ BaseSubobjectInfoMapTy VirtualBaseInfo;
+
+ /// NonVirtualBaseInfo - Map from all the direct non-virtual bases of the
+ /// class we're laying out to their base subobject info.
+ BaseSubobjectInfoMapTy NonVirtualBaseInfo;
+
+ /// ComputeBaseSubobjectInfo - Compute the base subobject information for the
+ /// bases of the given class.
+ void ComputeBaseSubobjectInfo(const CXXRecordDecl *RD);
+
+ /// ComputeBaseSubobjectInfo - Compute the base subobject information for a
+ /// single class and all of its base classes.
+ BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
+ bool IsVirtual,
+ BaseSubobjectInfo *Derived);
/// DeterminePrimaryBase - Determine the primary base of the given class.
void DeterminePrimaryBase(const CXXRecordDecl *RD);
@@ -387,43 +635,21 @@ class RecordLayoutBuilder {
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
/// LayoutNonVirtualBase - Lays out a single non-virtual base.
- void LayoutNonVirtualBase(const CXXRecordDecl *Base);
+ void LayoutNonVirtualBase(const BaseSubobjectInfo *Base);
- void AddPrimaryVirtualBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
- const CXXRecordDecl *MostDerivedClass);
+ void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
+ uint64_t Offset);
/// LayoutVirtualBases - Lays out all the virtual bases.
void LayoutVirtualBases(const CXXRecordDecl *RD,
const CXXRecordDecl *MostDerivedClass);
/// LayoutVirtualBase - Lays out a single virtual base.
- void LayoutVirtualBase(const CXXRecordDecl *Base);
+ void LayoutVirtualBase(const BaseSubobjectInfo *Base);
/// LayoutBase - Will lay out a base and return the offset where it was
/// placed, in bits.
- uint64_t LayoutBase(const CXXRecordDecl *Base, bool BaseIsVirtual);
-
- /// canPlaceRecordAtOffset - Return whether a record (either a base class
- /// or a field) can be placed at the given offset.
- /// Returns false if placing the record will result in two components
- /// (direct or indirect) of the same type having the same offset.
- bool canPlaceRecordAtOffset(const CXXRecordDecl *RD, uint64_t Offset,
- bool CheckVBases) const;
-
- /// canPlaceFieldAtOffset - Return whether a field can be placed at the given
- /// offset.
- bool canPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) const;
-
- /// UpdateEmptyClassOffsets - Called after a record (either a base class
- /// or a field) has been placed at the given offset. Will update the
- /// EmptyClassOffsets map if the class is empty or has any empty bases or
- /// fields.
- void UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset,
- bool UpdateVBases);
-
- /// UpdateEmptyClassOffsets - Called after a field has been placed at the
- /// given offset.
- void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset);
+ uint64_t LayoutBase(const BaseSubobjectInfo *Base);
/// InitializeLayout - Initialize record layout for the given record decl.
void InitializeLayout(const Decl *D);
@@ -575,14 +801,127 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
UpdateAlignment(Context.Target.getPointerAlign(0));
}
+BaseSubobjectInfo *
+RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
+ bool IsVirtual,
+ BaseSubobjectInfo *Derived) {
+ BaseSubobjectInfo *Info;
+
+ if (IsVirtual) {
+ // Check if we already have info about this virtual base.
+ BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
+ if (InfoSlot) {
+ assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");
+ return InfoSlot;
+ }
+
+ // We don't, create it.
+ InfoSlot = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
+ Info = InfoSlot;
+ } else {
+ Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
+ }
+
+ Info->Class = RD;
+ Info->IsVirtual = IsVirtual;
+ Info->Derived = 0;
+ Info->PrimaryVirtualBaseInfo = 0;
+
+ const CXXRecordDecl *PrimaryVirtualBase = 0;
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = 0;
+
+ // Check if this base has a primary virtual base.
+ if (RD->getNumVBases()) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ if (Layout.getPrimaryBaseWasVirtual()) {
+ // This base does have a primary virtual base.
+ PrimaryVirtualBase = Layout.getPrimaryBase();
+ assert(PrimaryVirtualBase && "Didn't have a primary virtual base!");
+
+ // Now check if we have base subobject info about this primary base.
+ PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
+
+ if (PrimaryVirtualBaseInfo) {
+ if (PrimaryVirtualBaseInfo->Derived) {
+ // We did have info about this primary base, and it turns out that it
+ // has already been claimed as a primary virtual base for another
+ // base.
+ PrimaryVirtualBase = 0;
+ } else {
+ // We can claim this base as our primary base.
+ Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
+ PrimaryVirtualBaseInfo->Derived = Info;
+ }
+ }
+ }
+ }
+
+ // Now go through all direct bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ bool IsVirtual = I->isVirtual();
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
+ }
+
+ if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
+ // Traversing the bases must have created the base info for our primary
+ // virtual base.
+ PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
+ assert(PrimaryVirtualBaseInfo &&
+ "Did not create a primary virtual base!");
+
+ // Claim the primary virtual base as our primary virtual base.
+ Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
+ PrimaryVirtualBaseInfo->Derived = Info;
+ }
+
+ return Info;
+}
+
+void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ bool IsVirtual = I->isVirtual();
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Compute the base subobject info for this base.
+ BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, 0);
+
+ if (IsVirtual) {
+ // ComputeBaseInfo has already added this base for us.
+ assert(VirtualBaseInfo.count(BaseDecl) &&
+ "Did not add virtual base!");
+ } else {
+ // Add the base info to the map of non-virtual bases.
+ assert(!NonVirtualBaseInfo.count(BaseDecl) &&
+ "Non-virtual base already exists!");
+ NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
+ }
+ }
+}
+
void
RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
- // First, determine the primary base class.
+ // Then, determine the primary base class.
DeterminePrimaryBase(RD);
+ // Compute base subobject info.
+ ComputeBaseSubobjectInfo(RD);
+
// If we have a primary base class, lay it out.
if (PrimaryBase) {
if (PrimaryBaseIsVirtual) {
+ // If the primary virtual base was a primary virtual base of some other
+ // base class we'll have to steal it.
+ BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
+ PrimaryBaseInfo->Derived = 0;
+
// We have a virtual primary base, insert it as an indirect primary base.
IndirectPrimaryBases.insert(PrimaryBase);
@@ -590,9 +929,15 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
"vbase already visited!");
VisitedVirtualBases.insert(PrimaryBase);
- LayoutVirtualBase(PrimaryBase);
- } else
- LayoutNonVirtualBase(PrimaryBase);
+ LayoutVirtualBase(PrimaryBaseInfo);
+ } else {
+ BaseSubobjectInfo *PrimaryBaseInfo =
+ NonVirtualBaseInfo.lookup(PrimaryBase);
+ assert(PrimaryBaseInfo &&
+ "Did not find base info for non-virtual primary base!");
+
+ LayoutNonVirtualBase(PrimaryBaseInfo);
+ }
}
// Now lay out the non-virtual bases.
@@ -603,81 +948,64 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
if (I->isVirtual())
continue;
- const CXXRecordDecl *Base =
+ const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
// Skip the primary base.
- if (Base == PrimaryBase && !PrimaryBaseIsVirtual)
+ if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
continue;
// Lay out the base.
- LayoutNonVirtualBase(Base);
+ BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.lookup(BaseDecl);
+ assert(BaseInfo && "Did not find base info for non-virtual base!");
+
+ LayoutNonVirtualBase(BaseInfo);
}
}
-void RecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *Base) {
+void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) {
// Layout the base.
- uint64_t Offset = LayoutBase(Base, /*BaseIsVirtual=*/false);
+ uint64_t Offset = LayoutBase(Base);
// Add its base class offset.
- if (!Bases.insert(std::make_pair(Base, Offset)).second)
- assert(false && "Added same base offset more than once!");
+ assert(!Bases.count(Base->Class) && "base offset already exists!");
+ Bases.insert(std::make_pair(Base->Class, Offset));
+
+ AddPrimaryVirtualBaseOffsets(Base, Offset);
}
void
-RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const CXXRecordDecl *RD,
- uint64_t Offset,
- const CXXRecordDecl *MostDerivedClass) {
- // We already have the offset for the primary base of the most derived class.
- if (RD != MostDerivedClass) {
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
-
- // If this is a primary virtual base and we haven't seen it before, add it.
- if (PrimaryBase && Layout.getPrimaryBaseWasVirtual() &&
- !VBases.count(PrimaryBase))
- VBases.insert(std::make_pair(PrimaryBase, Offset));
+RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
+ uint64_t Offset) {
+ // This base isn't interesting, it has no virtual bases.
+ if (!Info->Class->getNumVBases())
+ return;
+
+ // First, check if we have a virtual primary base to add offsets for.
+ if (Info->PrimaryVirtualBaseInfo) {
+ assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
+ "Primary virtual base is not virtual!");
+ if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
+ // Add the offset.
+ assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
+ "primary vbase offset already exists!");
+ VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
+ Offset));
+
+ // Traverse the primary virtual base.
+ AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
+ }
}
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- assert(!I->getType()->isDependentType() &&
- "Cannot layout class with dependent bases.");
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- if (!BaseDecl->getNumVBases()) {
- // This base isn't interesting since it doesn't have any virtual bases.
+ // Now go through all direct non-virtual bases.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
+ for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) {
+ const BaseSubobjectInfo *Base = Info->Bases[I];
+ if (Base->IsVirtual)
continue;
- }
-
- // Compute the offset of this base.
- uint64_t BaseOffset;
-
- if (I->isVirtual()) {
- // If we don't know this vbase yet, don't visit it. It will be visited
- // later.
- if (!VBases.count(BaseDecl)) {
- continue;
- }
-
- // Check if we've already visited this base.
- if (!VisitedVirtualBases.insert(BaseDecl))
- continue;
- // We want the vbase offset from the class we're currently laying out.
- BaseOffset = VBases[BaseDecl];
- } else if (RD == MostDerivedClass) {
- // We want the base offset from the class we're currently laying out.
- assert(Bases.count(BaseDecl) && "Did not find base!");
- BaseOffset = Bases[BaseDecl];
- } else {
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
- }
-
- AddPrimaryVirtualBaseOffsets(BaseDecl, BaseOffset, MostDerivedClass);
+ uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
+ AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
}
}
@@ -701,53 +1029,54 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
assert(!I->getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
- const CXXRecordDecl *Base =
+ const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
if (I->isVirtual()) {
- if (PrimaryBase != Base || !PrimaryBaseIsVirtual) {
- bool IndirectPrimaryBase = IndirectPrimaryBases.count(Base);
+ if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
+ bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
// Only lay out the virtual base if it's not an indirect primary base.
if (!IndirectPrimaryBase) {
// Only visit virtual bases once.
- if (!VisitedVirtualBases.insert(Base))
+ if (!VisitedVirtualBases.insert(BaseDecl))
continue;
- LayoutVirtualBase(Base);
+ const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
+ assert(BaseInfo && "Did not find virtual base info!");
+ LayoutVirtualBase(BaseInfo);
}
}
}
- if (!Base->getNumVBases()) {
+ if (!BaseDecl->getNumVBases()) {
// This base isn't interesting since it doesn't have any virtual bases.
continue;
}
- LayoutVirtualBases(Base, MostDerivedClass);
+ LayoutVirtualBases(BaseDecl, MostDerivedClass);
}
}
-void RecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *Base) {
+void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) {
+ assert(!Base->Derived && "Trying to lay out a primary virtual base!");
+
// Layout the base.
- uint64_t Offset = LayoutBase(Base, /*BaseIsVirtual=*/true);
+ uint64_t Offset = LayoutBase(Base);
// Add its base class offset.
- if (!VBases.insert(std::make_pair(Base, Offset)).second)
- assert(false && "Added same vbase offset more than once!");
+ assert(!VBases.count(Base->Class) && "vbase offset already exists!");
+ VBases.insert(std::make_pair(Base->Class, Offset));
+
+ AddPrimaryVirtualBaseOffsets(Base, Offset);
}
-uint64_t RecordLayoutBuilder::LayoutBase(const CXXRecordDecl *Base,
- bool BaseIsVirtual) {
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base);
+uint64_t RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class);
// If we have an empty base class, try to place it at offset 0.
- if (Base->isEmpty() &&
- EmptySubobjects->CanPlaceBaseAtOffset(Base, BaseIsVirtual, 0) &&
- canPlaceRecordAtOffset(Base, 0, /*CheckVBases=*/false)) {
- // We were able to place the class at offset 0.
- UpdateEmptyClassOffsets(Base, 0, /*UpdateVBases=*/false);
-
+ if (Base->Class->isEmpty() &&
+ EmptySubobjects->CanPlaceBaseAtOffset(Base, 0)) {
Size = std::max(Size, Layout.getSize());
return 0;
@@ -759,15 +1088,10 @@ uint64_t RecordLayoutBuilder::LayoutBase(const CXXRecordDecl *Base,
uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign);
// Try to place the base.
- while (true) {
- if (EmptySubobjects->CanPlaceBaseAtOffset(Base, BaseIsVirtual, Offset) &&
- canPlaceRecordAtOffset(Base, Offset, /*CheckVBases=*/false))
- break;
-
+ while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
Offset += BaseAlign;
- }
- if (!Base->isEmpty()) {
+ if (!Base->Class->isEmpty()) {
// Update the data size.
DataSize = Offset + Layout.getNonVirtualSize();
@@ -778,173 +1102,9 @@ uint64_t RecordLayoutBuilder::LayoutBase(const CXXRecordDecl *Base,
// Remember max struct/class alignment.
UpdateAlignment(BaseAlign);
- UpdateEmptyClassOffsets(Base, Offset, /*UpdateVBases=*/false);
return Offset;
}
-bool
-RecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
- uint64_t Offset,
- bool CheckVBases) const {
- // Look for an empty class with the same type at the same offset.
- for (EmptyClassOffsetsTy::const_iterator I =
- EmptyClassOffsets.lower_bound(Offset),
- E = EmptyClassOffsets.upper_bound(Offset); I != E; ++I) {
-
- if (I->second == RD)
- return false;
- }
-
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
- // Check bases.
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- assert(!I->getType()->isDependentType() &&
- "Cannot layout class with dependent bases.");
- if (I->isVirtual())
- continue;
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl);
-
- if (!canPlaceRecordAtOffset(BaseDecl, Offset + BaseOffset,
- /*CheckVBases=*/false))
- return false;
- }
-
- // Check fields.
- unsigned FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I, ++FieldNo) {
- const FieldDecl *FD = *I;
-
- uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
-
- if (!canPlaceFieldAtOffset(FD, Offset + FieldOffset))
- return false;
- }
-
- if (CheckVBases) {
- // FIXME: virtual bases.
- }
-
- return true;
-}
-
-bool RecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD,
- uint64_t Offset) const {
- QualType T = FD->getType();
- if (const RecordType *RT = T->getAs<RecordType>()) {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- return canPlaceRecordAtOffset(RD, Offset, /*CheckVBases=*/true);
- }
-
- if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
- QualType ElemTy = Context.getBaseElementType(AT);
- const RecordType *RT = ElemTy->getAs<RecordType>();
- if (!RT)
- return true;
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
- return true;
-
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
- uint64_t NumElements = Context.getConstantArrayElementCount(AT);
- uint64_t ElementOffset = Offset;
- for (uint64_t I = 0; I != NumElements; ++I) {
- if (!canPlaceRecordAtOffset(RD, ElementOffset, /*CheckVBases=*/true))
- return false;
-
- ElementOffset += Layout.getSize();
- }
- }
-
- return true;
-}
-
-void RecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
- uint64_t Offset,
- bool UpdateVBases) {
- if (RD->isEmpty())
- EmptyClassOffsets.insert(std::make_pair(Offset, RD));
-
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
- // Update bases.
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- assert(!I->getType()->isDependentType() &&
- "Cannot layout class with dependent bases.");
- if (I->isVirtual())
- continue;
-
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- uint64_t BaseClassOffset = Layout.getBaseClassOffset(Base);
- UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset,
- /*UpdateVBases=*/false);
- }
-
- // Update fields.
- unsigned FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I, ++FieldNo) {
- const FieldDecl *FD = *I;
-
- uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
- UpdateEmptyClassOffsets(FD, Offset + FieldOffset);
- }
-
- const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
-
- if (UpdateVBases) {
- // FIXME: Update virtual bases.
- } else if (PrimaryBase && Layout.getPrimaryBaseWasVirtual()) {
- // We always want to update the offsets of a primary virtual base.
- assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
- "primary base class offset must always be 0!");
- UpdateEmptyClassOffsets(PrimaryBase, Offset, /*UpdateVBases=*/false);
- }
-}
-
-void
-RecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD,
- uint64_t Offset) {
- QualType T = FD->getType();
-
- if (const RecordType *RT = T->getAs<RecordType>()) {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- UpdateEmptyClassOffsets(RD, Offset, /*UpdateVBases=*/true);
- return;
- }
- }
-
- if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
- QualType ElemTy = Context.getBaseElementType(AT);
- const RecordType *RT = ElemTy->getAs<RecordType>();
- if (!RT)
- return;
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
- return;
-
- const ASTRecordLayout &Info = Context.getASTRecordLayout(RD);
-
- uint64_t NumElements = Context.getConstantArrayElementCount(AT);
- uint64_t ElementOffset = Offset;
-
- for (uint64_t I = 0; I != NumElements; ++I) {
- UpdateEmptyClassOffsets(RD, ElementOffset, /*UpdateVBases=*/true);
- ElementOffset += Info.getSize();
- }
- }
-}
-
void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
IsUnion = RD->isUnion();
@@ -992,7 +1152,6 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
LayoutVirtualBases(RD, RD);
VisitedVirtualBases.clear();
- AddPrimaryVirtualBaseOffsets(RD, 0, RD);
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
@@ -1137,7 +1296,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// Check if we need to add padding to give the field the correct alignment.
if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
- FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
+ FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
// Padding members don't affect overall alignment.
if (!D->getIdentifier())
@@ -1208,17 +1367,12 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
// Round up the current record size to the field's alignment boundary.
FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
- if (!IsUnion) {
- while (true) {
- // Check if we can place the field at this offset.
- if (canPlaceFieldAtOffset(D, FieldOffset))
- break;
-
+ if (!IsUnion && EmptySubobjects) {
+ // Check if we can place the field at this offset.
+ while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
// We couldn't place the field at the offset. Try again at a new offset.
FieldOffset += FieldAlign;
}
-
- UpdateEmptyClassOffsets(D, FieldOffset);
}
// Place this field at the current location.
@@ -1261,8 +1415,6 @@ void RecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
const CXXMethodDecl *
RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
- assert(RD->isDynamicClass() && "Class does not have any virtual methods!");
-
// If a class isn't polymorphic it doesn't have a key function.
if (!RD->isPolymorphic())
return 0;
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
index 80f5695..6dbe8f4 100644
--- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -499,14 +499,101 @@ void DeclStmt::DoDestroy(ASTContext &C) {
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)
+{
+ setConditionVariable(C, var);
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[THEN] = then;
+ SubExprs[ELSE] = elsev;
+}
+
+VarDecl *IfStmt::getConditionVariable() const {
+ if (!SubExprs[VAR])
+ return 0;
+
+ DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ return cast<VarDecl>(DS->getSingleDecl());
+}
+
+void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
+ if (!V) {
+ SubExprs[VAR] = 0;
+ return;
+ }
+
+ SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
+ V->getSourceRange().getBegin(),
+ 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)
+ : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP)
+{
+ SubExprs[INIT] = Init;
+ setConditionVariable(C, condVar);
+ SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
+ SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
+ SubExprs[BODY] = Body;
+}
+
+VarDecl *ForStmt::getConditionVariable() const {
+ if (!SubExprs[CONDVAR])
+ return 0;
+
+ DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
+ return cast<VarDecl>(DS->getSingleDecl());
+}
+
+void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
+ if (!V) {
+ SubExprs[CONDVAR] = 0;
+ return;
+ }
+
+ SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V),
+ V->getSourceRange().getBegin(),
+ 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)
+{
+ setConditionVariable(C, Var);
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[BODY] = NULL;
+}
+
+VarDecl *SwitchStmt::getConditionVariable() const {
+ if (!SubExprs[VAR])
+ return 0;
+
+ DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ return cast<VarDecl>(DS->getSingleDecl());
+}
+
+void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
+ if (!V) {
+ SubExprs[VAR] = 0;
+ return;
+ }
+
+ SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
+ V->getSourceRange().getBegin(),
+ 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
@@ -521,6 +608,35 @@ void SwitchStmt::DoDestroy(ASTContext &C) {
BranchDestroy(C, this, SubExprs, END_EXPR);
}
+WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
+ SourceLocation WL)
+: Stmt(WhileStmtClass)
+{
+ setConditionVariable(C, Var);
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[BODY] = body;
+ WhileLoc = WL;
+}
+
+VarDecl *WhileStmt::getConditionVariable() const {
+ if (!SubExprs[VAR])
+ return 0;
+
+ DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ return cast<VarDecl>(DS->getSingleDecl());
+}
+
+void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
+ if (!V) {
+ SubExprs[VAR] = 0;
+ return;
+ }
+
+ SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
+ V->getSourceRange().getBegin(),
+ V->getSourceRange().getEnd());
+}
+
void WhileStmt::DoDestroy(ASTContext &C) {
BranchDestroy(C, this, SubExprs, END_EXPR);
}
@@ -572,26 +688,26 @@ Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
// IfStmt
Stmt::child_iterator IfStmt::child_begin() {
- return child_iterator(Var, &SubExprs[0]);
+ return &SubExprs[0];
}
Stmt::child_iterator IfStmt::child_end() {
- return child_iterator(0, &SubExprs[0]+END_EXPR);
+ return &SubExprs[0]+END_EXPR;
}
// SwitchStmt
Stmt::child_iterator SwitchStmt::child_begin() {
- return child_iterator(Var, &SubExprs[0]);
+ return &SubExprs[0];
}
Stmt::child_iterator SwitchStmt::child_end() {
- return child_iterator(0, &SubExprs[0]+END_EXPR);
+ return &SubExprs[0]+END_EXPR;
}
// WhileStmt
Stmt::child_iterator WhileStmt::child_begin() {
- return child_iterator(Var, &SubExprs[0]);
+ return &SubExprs[0];
}
Stmt::child_iterator WhileStmt::child_end() {
- return child_iterator(0, &SubExprs[0]+END_EXPR);
+ return &SubExprs[0]+END_EXPR;
}
// DoStmt
@@ -600,10 +716,10 @@ Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
// ForStmt
Stmt::child_iterator ForStmt::child_begin() {
- return child_iterator(CondVar, &SubExprs[0]);
+ return &SubExprs[0];
}
Stmt::child_iterator ForStmt::child_end() {
- return child_iterator(0, &SubExprs[0]+END_EXPR);
+ return &SubExprs[0]+END_EXPR;
}
// ObjCForCollectionStmt
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
index 9bef49c..7043c35 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
@@ -682,7 +682,7 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
bool StmtPrinter::PrintOffsetOfDesignator(Expr *E) {
if (isa<UnaryOperator>(E)) {
// Base case, print the type and comma.
- OS << E->getType().getAsString() << ", ";
+ OS << E->getType().getAsString(Policy) << ", ";
return true;
} else if (ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
PrintOffsetOfDesignator(ASE->getLHS());
@@ -706,7 +706,7 @@ void StmtPrinter::VisitUnaryOffsetOf(UnaryOperator *Node) {
void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
OS << "__builtin_offsetof(";
- OS << Node->getTypeSourceInfo()->getType().getAsString() << ", ";
+ OS << Node->getTypeSourceInfo()->getType().getAsString(Policy) << ", ";
bool PrintedSomething = false;
for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) {
OffsetOfExpr::OffsetOfNode ON = Node->getComponent(i);
@@ -740,7 +740,7 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
void StmtPrinter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
OS << (Node->isSizeOf() ? "sizeof" : "__alignof");
if (Node->isArgumentType())
- OS << "(" << Node->getArgumentType().getAsString() << ")";
+ OS << "(" << Node->getArgumentType().getAsString(Policy) << ")";
else {
OS << " ";
PrintExpr(Node->getArgumentExpr());
@@ -802,11 +802,11 @@ void StmtPrinter::VisitExplicitCastExpr(ExplicitCastExpr *) {
assert(0 && "ExplicitCastExpr is an abstract class");
}
void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
- OS << "(" << Node->getType().getAsString() << ")";
+ OS << "(" << Node->getType().getAsString(Policy) << ")";
PrintExpr(Node->getSubExpr());
}
void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) {
- OS << "(" << Node->getType().getAsString() << ")";
+ OS << "(" << Node->getType().getAsString(Policy) << ")";
PrintExpr(Node->getInitializer());
}
void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
@@ -852,8 +852,8 @@ void StmtPrinter::VisitStmtExpr(StmtExpr *E) {
void StmtPrinter::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) {
OS << "__builtin_types_compatible_p(";
- OS << Node->getArgType1().getAsString() << ",";
- OS << Node->getArgType2().getAsString() << ")";
+ OS << Node->getArgType1().getAsString(Policy) << ",";
+ OS << Node->getArgType2().getAsString(Policy) << ")";
}
void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) {
@@ -947,7 +947,7 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
OS << "__builtin_va_arg(";
PrintExpr(Node->getSubExpr());
OS << ", ";
- OS << Node->getType().getAsString();
+ OS << Node->getType().getAsString(Policy);
OS << ")";
}
@@ -1002,7 +1002,7 @@ void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
OS << Node->getCastName() << '<';
- OS << Node->getTypeAsWritten().getAsString() << ">(";
+ OS << Node->getTypeAsWritten().getAsString(Policy) << ">(";
PrintExpr(Node->getSubExpr());
OS << ")";
}
@@ -1026,7 +1026,7 @@ void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) {
void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
OS << "typeid(";
if (Node->isTypeOperand()) {
- OS << Node->getTypeOperand().getAsString();
+ OS << Node->getTypeOperand().getAsString(Policy);
} else {
PrintExpr(Node->getExprOperand());
}
@@ -1059,7 +1059,7 @@ void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
}
void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
- OS << Node->getType().getAsString();
+ OS << Node->getType().getAsString(Policy);
OS << "(";
PrintExpr(Node->getSubExpr());
OS << ")";
@@ -1074,7 +1074,7 @@ void StmtPrinter::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *Node) {
}
void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
- OS << Node->getType().getAsString();
+ OS << Node->getType().getAsString(Policy);
OS << "(";
for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
ArgEnd = Node->arg_end();
@@ -1086,8 +1086,8 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
OS << ")";
}
-void StmtPrinter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *Node) {
- OS << Node->getType().getAsString() << "()";
+void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) {
+ OS << Node->getType().getAsString(Policy) << "()";
}
void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
@@ -1177,7 +1177,7 @@ void StmtPrinter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
void
StmtPrinter::VisitCXXUnresolvedConstructExpr(
CXXUnresolvedConstructExpr *Node) {
- OS << Node->getTypeAsWritten().getAsString();
+ OS << Node->getTypeAsWritten().getAsString(Policy);
OS << "(";
for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(),
ArgEnd = Node->arg_end();
@@ -1254,7 +1254,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) {
void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
OS << getTypeTraitName(E->getTrait()) << "("
- << E->getQueriedType().getAsString() << ")";
+ << E->getQueriedType().getAsString(Policy) << ")";
}
// Obj-C
@@ -1265,7 +1265,7 @@ void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
}
void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
- OS << "@encode(" << Node->getEncodedType().getAsString() << ')';
+ OS << "@encode(" << Node->getEncodedType().getAsString(Policy) << ')';
}
void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
index ac3a9ee..cff86a4 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
@@ -211,9 +211,11 @@ void StmtProfiler::VisitExpr(Expr *S) {
void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) {
VisitExpr(S);
- VisitNestedNameSpecifier(S->getQualifier());
+ if (!Canonical)
+ VisitNestedNameSpecifier(S->getQualifier());
VisitDecl(S->getDecl());
- VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+ if (!Canonical)
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitPredefinedExpr(PredefinedExpr *S) {
@@ -307,7 +309,8 @@ void StmtProfiler::VisitCallExpr(CallExpr *S) {
void StmtProfiler::VisitMemberExpr(MemberExpr *S) {
VisitExpr(S);
VisitDecl(S->getMemberDecl());
- VisitNestedNameSpecifier(S->getQualifier());
+ if (!Canonical)
+ VisitNestedNameSpecifier(S->getQualifier());
ID.AddBoolean(S->isArrow());
}
@@ -428,6 +431,8 @@ void StmtProfiler::VisitBlockDeclRefExpr(BlockDeclRefExpr *S) {
VisitDecl(S->getDecl());
ID.AddBoolean(S->isByRef());
ID.AddBoolean(S->isConstQualAdded());
+ if (S->getCopyConstructorExpr())
+ Visit(S->getCopyConstructorExpr());
}
static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
@@ -719,7 +724,7 @@ void StmtProfiler::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *S) {
VisitCXXConstructExpr(S);
}
-void StmtProfiler::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *S) {
+void StmtProfiler::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *S) {
VisitExpr(S);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
index 1c775ef..02e6488 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
@@ -90,6 +90,33 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
}
}
+bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
+ if (getKind() != Other.getKind()) return false;
+
+ switch (getKind()) {
+ case Null:
+ case Type:
+ case Declaration:
+ case Template:
+ case Expression:
+ return TypeOrValue == Other.TypeOrValue;
+
+ case Integral:
+ return getIntegralType() == Other.getIntegralType() &&
+ *getAsIntegral() == *Other.getAsIntegral();
+
+ case Pack:
+ if (Args.NumArgs != Other.Args.NumArgs) return false;
+ for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
+ if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
+ return false;
+ return true;
+ }
+
+ // Suppress warnings.
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// TemplateArgumentLoc Implementation
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
index 14722f7..ef7b315 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
@@ -21,6 +21,17 @@
using namespace clang;
using namespace llvm;
+TemplateName::NameKind TemplateName::getKind() const {
+ if (Storage.is<TemplateDecl *>())
+ return Template;
+ if (Storage.is<OverloadedTemplateStorage *>())
+ return OverloadedTemplate;
+ if (Storage.is<QualifiedTemplateName *>())
+ return QualifiedTemplate;
+ assert(Storage.is<DependentTemplateName *>() && "There's a case unhandled!");
+ return DependentTemplate;
+}
+
TemplateDecl *TemplateName::getAsTemplateDecl() const {
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
return Template;
diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp
index 1aab65e..d7929304 100644
--- a/contrib/llvm/tools/clang/lib/AST/Type.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp
@@ -439,17 +439,49 @@ bool Type::isIntegerType() const {
return false;
}
-bool Type::isIntegralType() const {
+/// \brief Determine whether this type is an integral type.
+///
+/// This routine determines whether the given type is an integral type per
+/// C++ [basic.fundamental]p7. Although the C standard does not define the
+/// term "integral type", it has a similar term "integer type", and in C++
+/// the two terms are equivalent. However, C's "integer type" includes
+/// enumeration types, while C++'s "integer type" does not. The \c ASTContext
+/// parameter is used to determine whether we should be following the C or
+/// C++ rules when determining whether this type is an integral/integer type.
+///
+/// For cases where C permits "an integer type" and C++ permits "an integral
+/// type", use this routine.
+///
+/// For cases where C permits "an integer type" and C++ permits "an integral
+/// or enumeration type", use \c isIntegralOrEnumerationType() instead.
+///
+/// \param Ctx The context in which this type occurs.
+///
+/// \returns true if the type is considered an integral type, false otherwise.
+bool Type::isIntegralType(ASTContext &Ctx) const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
- if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
- if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
- return true; // Complete enum types are integral.
- // FIXME: In C++, enum types are never integral.
+
+ if (!Ctx.getLangOptions().CPlusPlus)
+ if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
+ if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
+ return true; // Complete enum types are integral in C.
+
return false;
}
+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;
+
+ return false;
+}
+
bool Type::isEnumeralType() const {
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
return TT->getDecl()->isEnum();
@@ -531,16 +563,19 @@ bool Type::isFloatingType() const {
BT->getKind() <= BuiltinType::LongDouble;
if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
+ return false;
+}
+
+bool Type::hasFloatingRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isFloatingType();
- return false;
+ else
+ return isFloatingType();
}
bool Type::isRealFloatingType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->isFloatingPoint();
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
- return VT->getElementType()->isRealFloatingType();
return false;
}
@@ -550,8 +585,6 @@ bool Type::isRealType() const {
BT->getKind() <= BuiltinType::LongDouble;
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
return TT->getDecl()->isEnum() && TT->getDecl()->isDefinition();
- if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
- return VT->getElementType()->isRealType();
return false;
}
@@ -563,7 +596,7 @@ bool Type::isArithmeticType() const {
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
// If a body isn't seen by the time we get here, return false.
return ET->getDecl()->isDefinition();
- return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
+ return isa<ComplexType>(CanonicalType);
}
bool Type::isScalarType() const {
@@ -768,6 +801,7 @@ bool Type::isSpecifierType() const {
case TemplateSpecialization:
case Elaborated:
case DependentName:
+ case DependentTemplateSpecialization:
case ObjCInterface:
case ObjCObject:
case ObjCObjectPointer: // FIXME: object pointers aren't really specifiers
@@ -856,12 +890,56 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
}
}
+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,
+ unsigned NumArgs, const TemplateArgument *Args,
+ QualType Canon)
+ : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true),
+ NNS(NNS), Name(Name), NumArgs(NumArgs) {
+ assert(NNS && NNS->isDependent() &&
+ "DependentTemplateSpecializatonType requires dependent qualifier");
+ for (unsigned I = 0; I != NumArgs; ++I)
+ new (&getArgBuffer()[I]) TemplateArgument(Args[I]);
+}
+
+void
+DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
+ ASTContext &Context,
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *Qualifier,
+ const IdentifierInfo *Name,
+ unsigned NumArgs,
+ const TemplateArgument *Args) {
+ ID.AddInteger(Keyword);
+ ID.AddPointer(Qualifier);
+ ID.AddPointer(Name);
+ for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
+ Args[Idx].Profile(ID, Context);
+}
+
bool Type::isElaboratedTypeSpecifier() const {
ElaboratedTypeKeyword Keyword;
if (const ElaboratedType *Elab = dyn_cast<ElaboratedType>(this))
Keyword = Elab->getKeyword();
else if (const DependentNameType *DepName = dyn_cast<DependentNameType>(this))
Keyword = DepName->getKeyword();
+ else if (const DependentTemplateSpecializationType *DepTST =
+ dyn_cast<DependentTemplateSpecializationType>(this))
+ Keyword = DepTST->getKeyword();
else
return false;
@@ -914,6 +992,22 @@ const char *BuiltinType::getName(const LangOptions &LO) const {
void FunctionType::ANCHOR() {} // Key function for FunctionType.
+QualType QualType::getNonLValueExprType(ASTContext &Context) const {
+ if (const ReferenceType *RefType = getTypePtr()->getAs<ReferenceType>())
+ return RefType->getPointeeType();
+
+ // C++0x [basic.lval]:
+ // Class prvalues can have cv-qualified types; non-class prvalues always
+ // have cv-unqualified types.
+ //
+ // See also C99 6.3.2.1p2.
+ if (!Context.getLangOptions().CPlusPlus ||
+ (!getTypePtr()->isDependentType() && !getTypePtr()->isRecordType()))
+ return getUnqualifiedType();
+
+ return *this;
+}
+
llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) {
switch (CC) {
case CC_Default: llvm_unreachable("no name for default cc");
@@ -1085,14 +1179,12 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) {
}
TemplateSpecializationType::
-TemplateSpecializationType(ASTContext &Context, TemplateName T,
- bool IsCurrentInstantiation,
+TemplateSpecializationType(TemplateName T,
const TemplateArgument *Args,
unsigned NumArgs, QualType Canon)
: Type(TemplateSpecialization,
Canon.isNull()? QualType(this, 0) : Canon,
T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)),
- ContextAndCurrentInstantiation(&Context, IsCurrentInstantiation),
Template(T), NumArgs(NumArgs) {
assert((!Canon.isNull() ||
T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) &&
@@ -1113,25 +1205,12 @@ void TemplateSpecializationType::Destroy(ASTContext& C) {
}
}
-TemplateSpecializationType::iterator
-TemplateSpecializationType::end() const {
- return begin() + getNumArgs();
-}
-
-const TemplateArgument &
-TemplateSpecializationType::getArg(unsigned Idx) const {
- assert(Idx < getNumArgs() && "Template argument out of range");
- return getArgs()[Idx];
-}
-
void
TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
TemplateName T,
- bool IsCurrentInstantiation,
const TemplateArgument *Args,
unsigned NumArgs,
ASTContext &Context) {
- ID.AddBoolean(IsCurrentInstantiation);
T.Profile(ID);
for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
Args[Idx].Profile(ID, Context);
diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
index 35a7e09..a08ee1a 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
@@ -227,12 +227,13 @@ void TypePrinter::PrintDependentSizedExtVector(
}
void TypePrinter::PrintVector(const VectorType *T, std::string &S) {
- if (T->isAltiVec()) {
- if (T->isPixel())
+ if (T->getAltiVecSpecific() != VectorType::NotAltiVec) {
+ if (T->getAltiVecSpecific() == VectorType::Pixel)
S = "__vector __pixel " + S;
else {
Print(T->getElementType(), S);
- S = "__vector " + S;
+ S = ((T->getAltiVecSpecific() == VectorType::Bool)
+ ? "__vector __bool " : "__vector ") + S;
}
} else {
// FIXME: We prefer to print the size directly here, but have no way
@@ -452,11 +453,13 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
if (!HasKindDecoration)
OS << " " << D->getKindName();
- PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
- D->getLocation());
- OS << " at " << PLoc.getFilename()
- << ':' << PLoc.getLine()
- << ':' << PLoc.getColumn();
+ if (D->getLocation().isValid()) {
+ PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
+ D->getLocation());
+ OS << " at " << PLoc.getFilename()
+ << ':' << PLoc.getLine()
+ << ':' << PLoc.getColumn();
+ }
}
OS << '>';
@@ -578,15 +581,31 @@ void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S)
T->getQualifier()->print(OS, Policy);
- if (const IdentifierInfo *Ident = T->getIdentifier())
- OS << Ident->getName();
- else if (const TemplateSpecializationType *Spec = T->getTemplateId()) {
- Spec->getTemplateName().print(OS, Policy, true);
- OS << TemplateSpecializationType::PrintTemplateArgumentList(
- Spec->getArgs(),
- Spec->getNumArgs(),
+ OS << T->getIdentifier()->getName();
+ }
+
+ if (S.empty())
+ S.swap(MyString);
+ else
+ S = MyString + ' ' + S;
+}
+
+void TypePrinter::PrintDependentTemplateSpecialization(
+ const DependentTemplateSpecializationType *T, std::string &S) {
+ std::string MyString;
+ {
+ llvm::raw_string_ostream OS(MyString);
+
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ETK_None)
+ OS << " ";
+
+ T->getQualifier()->print(OS, Policy);
+ OS << T->getIdentifier()->getName();
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ T->getArgs(),
+ T->getNumArgs(),
Policy);
- }
}
if (S.empty())
OpenPOWER on IntegriCloud