aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/APValue.cpp50
-rw-r--r--lib/AST/ASTContext.cpp705
-rw-r--r--lib/AST/ASTDiagnostic.cpp46
-rw-r--r--lib/AST/ASTImporter.cpp612
-rw-r--r--lib/AST/CMakeLists.txt5
-rw-r--r--lib/AST/CXXInheritance.cpp12
-rw-r--r--lib/AST/Decl.cpp172
-rw-r--r--lib/AST/DeclBase.cpp141
-rw-r--r--lib/AST/DeclCXX.cpp97
-rw-r--r--lib/AST/DeclObjC.cpp179
-rw-r--r--lib/AST/DeclPrinter.cpp277
-rw-r--r--lib/AST/DeclTemplate.cpp52
-rw-r--r--lib/AST/DeclarationName.cpp25
-rw-r--r--lib/AST/DumpXML.cpp39
-rw-r--r--lib/AST/Expr.cpp423
-rw-r--r--lib/AST/ExprCXX.cpp38
-rw-r--r--lib/AST/ExprClassification.cpp3
-rw-r--r--lib/AST/ExprConstant.cpp180
-rw-r--r--lib/AST/ExternalASTSource.cpp4
-rw-r--r--lib/AST/InheritViz.cpp8
-rw-r--r--lib/AST/ItaniumCXXABI.cpp2
-rw-r--r--lib/AST/ItaniumMangle.cpp116
-rw-r--r--lib/AST/Mangle.cpp16
-rw-r--r--lib/AST/MicrosoftCXXABI.cpp4
-rw-r--r--lib/AST/MicrosoftMangle.cpp149
-rw-r--r--lib/AST/NestedNameSpecifier.cpp4
-rw-r--r--lib/AST/ParentMap.cpp8
-rw-r--r--lib/AST/RecordLayout.cpp12
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp419
-rw-r--r--lib/AST/SelectorLocationsKind.cpp128
-rw-r--r--lib/AST/Stmt.cpp30
-rw-r--r--lib/AST/StmtDumper.cpp36
-rw-r--r--lib/AST/StmtPrinter.cpp102
-rw-r--r--lib/AST/StmtProfile.cpp9
-rw-r--r--lib/AST/TemplateBase.cpp72
-rw-r--r--lib/AST/TemplateName.cpp6
-rw-r--r--lib/AST/Type.cpp116
-rw-r--r--lib/AST/TypeLoc.cpp3
-rw-r--r--lib/AST/TypePrinter.cpp15
-rw-r--r--lib/AST/VTTBuilder.cpp212
-rw-r--r--lib/AST/VTableBuilder.cpp2404
41 files changed, 5418 insertions, 1513 deletions
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index ebe99b12cdab..6f63a32dd2ed 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -13,7 +13,10 @@
#include "clang/AST/APValue.h"
#include "clang/AST/CharUnits.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace clang;
namespace {
@@ -89,9 +92,9 @@ static double GetApproxValue(const llvm::APFloat &F) {
return V.convertToDouble();
}
-void APValue::print(llvm::raw_ostream &OS) const {
+void APValue::print(raw_ostream &OS) const {
switch (getKind()) {
- default: assert(0 && "Unknown APValue kind!");
+ default: llvm_unreachable("Unknown APValue kind!");
case Uninitialized:
OS << "Uninitialized";
return;
@@ -118,6 +121,49 @@ void APValue::print(llvm::raw_ostream &OS) const {
}
}
+static void WriteShortAPValueToStream(raw_ostream& Out,
+ const APValue& V) {
+ switch (V.getKind()) {
+ default: llvm_unreachable("Unknown APValue kind!");
+ case APValue::Uninitialized:
+ Out << "Uninitialized";
+ break;
+ case APValue::Int:
+ Out << V.getInt();
+ break;
+ case APValue::Float:
+ Out << GetApproxValue(V.getFloat());
+ break;
+ case APValue::Vector:
+ Out << '[';
+ WriteShortAPValueToStream(Out, V.getVectorElt(0));
+ for (unsigned i = 1; i != V.getVectorLength(); ++i) {
+ Out << ", ";
+ WriteShortAPValueToStream(Out, V.getVectorElt(i));
+ }
+ Out << ']';
+ break;
+ case APValue::ComplexInt:
+ Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
+ break;
+ case APValue::ComplexFloat:
+ Out << GetApproxValue(V.getComplexFloatReal()) << "+"
+ << GetApproxValue(V.getComplexFloatImag()) << "i";
+ break;
+ case APValue::LValue:
+ Out << "LValue: <todo>";
+ break;
+ }
+}
+
+const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
+ const APValue &V) {
+ llvm::SmallString<64> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ WriteShortAPValueToStream(Out, V);
+ return DB << Out.str();
+}
+
const Expr* APValue::getLValueBase() const {
assert(isLValue() && "Invalid accessor");
return ((const LV*)(const void*)Data)->Base;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 6eada6e22f4e..462428086ddd 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -30,6 +30,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Capacity.h"
#include "CXXABI.h"
#include <map>
@@ -49,7 +50,7 @@ unsigned ASTContext::NumImplicitDestructors;
unsigned ASTContext::NumImplicitDestructorsDeclared;
enum FloatingRank {
- FloatRank, DoubleRank, LongDoubleRank
+ HalfRank, FloatRank, DoubleRank, LongDoubleRank
};
void
@@ -104,7 +105,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
// Build a canonical template parameter list.
TemplateParameterList *Params = TTP->getTemplateParameters();
- llvm::SmallVector<NamedDecl *, 4> CanonParams;
+ SmallVector<NamedDecl *, 4> CanonParams;
CanonParams.reserve(Params->size());
for (TemplateParameterList::const_iterator P = Params->begin(),
PEnd = Params->end();
@@ -123,8 +124,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T);
NonTypeTemplateParmDecl *Param;
if (NTTP->isExpandedParameterPack()) {
- llvm::SmallVector<QualType, 2> ExpandedTypes;
- llvm::SmallVector<TypeSourceInfo *, 2> ExpandedTInfos;
+ SmallVector<QualType, 2> ExpandedTypes;
+ SmallVector<TypeSourceInfo *, 2> ExpandedTInfos;
for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) {
ExpandedTypes.push_back(getCanonicalType(NTTP->getExpansionType(I)));
ExpandedTInfos.push_back(
@@ -195,7 +196,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
return 0;
}
-static const LangAS::Map &getAddressSpaceMap(const TargetInfo &T,
+static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
const LangOptions &LOpts) {
if (LOpts.FakeAddressSpaceMap) {
// The fake address space map must have a distinct entry for each
@@ -205,41 +206,46 @@ static const LangAS::Map &getAddressSpaceMap(const TargetInfo &T,
2, // opencl_local
3 // opencl_constant
};
- return FakeAddrSpaceMap;
+ return &FakeAddrSpaceMap;
} else {
- return T.getAddressSpaceMap();
+ return &T.getAddressSpaceMap();
}
}
-ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
- const TargetInfo &t,
+ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
+ const TargetInfo *t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
- unsigned size_reserve) :
- FunctionProtoTypes(this_()),
- TemplateSpecializationTypes(this_()),
- DependentTemplateSpecializationTypes(this_()),
- SubstTemplateTemplateParmPacks(this_()),
- GlobalNestedNameSpecifier(0), IsInt128Installed(false),
- CFConstantStringTypeDecl(0), NSConstantStringTypeDecl(0),
- ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0),
- jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0),
- BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0),
- NullTypeSourceInfo(QualType()),
- SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)),
- AddrSpaceMap(getAddressSpaceMap(t, LOpts)), Target(t),
- Idents(idents), Selectors(sels),
- BuiltinInfo(builtins),
- DeclarationNames(*this),
- ExternalSource(0), Listener(0), PrintingPolicy(LOpts),
- LastSDM(0, 0),
- UniqueBlockByRefTypeID(0) {
- ObjCIdRedefinitionType = QualType();
- ObjCClassRedefinitionType = QualType();
- ObjCSelRedefinitionType = QualType();
+ unsigned size_reserve,
+ bool DelayInitialization)
+ : FunctionProtoTypes(this_()),
+ TemplateSpecializationTypes(this_()),
+ DependentTemplateSpecializationTypes(this_()),
+ SubstTemplateTemplateParmPacks(this_()),
+ GlobalNestedNameSpecifier(0),
+ Int128Decl(0), UInt128Decl(0),
+ ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0),
+ CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0),
+ FILEDecl(0),
+ jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0),
+ BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0),
+ NullTypeSourceInfo(QualType()),
+ SourceMgr(SM), LangOpts(LOpts),
+ AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts),
+ Idents(idents), Selectors(sels),
+ BuiltinInfo(builtins),
+ DeclarationNames(*this),
+ ExternalSource(0), Listener(0),
+ LastSDM(0, 0),
+ UniqueBlockByRefTypeID(0)
+{
if (size_reserve > 0) Types.reserve(size_reserve);
TUDecl = TranslationUnitDecl::Create(*this);
- InitBuiltinTypes();
+
+ if (!DelayInitialization) {
+ assert(t && "No target supplied for ASTContext initialization");
+ InitBuiltinTypes(*t);
+ }
}
ASTContext::~ASTContext() {
@@ -347,6 +353,33 @@ void ASTContext::PrintStats() const {
BumpAlloc.PrintStats();
}
+TypedefDecl *ASTContext::getInt128Decl() const {
+ if (!Int128Decl) {
+ TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(Int128Ty);
+ Int128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
+ getTranslationUnitDecl(),
+ SourceLocation(),
+ SourceLocation(),
+ &Idents.get("__int128_t"),
+ TInfo);
+ }
+
+ return Int128Decl;
+}
+
+TypedefDecl *ASTContext::getUInt128Decl() const {
+ if (!UInt128Decl) {
+ TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(UnsignedInt128Ty);
+ UInt128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
+ getTranslationUnitDecl(),
+ SourceLocation(),
+ SourceLocation(),
+ &Idents.get("__uint128_t"),
+ TInfo);
+ }
+
+ return UInt128Decl;
+}
void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K);
@@ -354,9 +387,16 @@ void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
Types.push_back(Ty);
}
-void ASTContext::InitBuiltinTypes() {
+void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
+ assert((!this->Target || this->Target == &Target) &&
+ "Incorrect target reinitialization");
assert(VoidTy.isNull() && "Context reinitialized?");
+ this->Target = &Target;
+
+ ABI.reset(createCXXABI(Target));
+ AddrSpaceMap = getAddressSpaceMap(Target, LangOpts);
+
// C99 6.2.5p19.
InitBuiltinType(VoidTy, BuiltinType::Void);
@@ -431,11 +471,6 @@ void ASTContext::InitBuiltinTypes() {
BuiltinVaListType = QualType();
- // "Builtin" typedefs set by Sema::ActOnTranslationUnitScope().
- ObjCIdTypedefType = QualType();
- ObjCClassTypedefType = QualType();
- ObjCSelTypedefType = QualType();
-
// Builtin types for 'id', 'Class', and 'SEL'.
InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
@@ -448,9 +483,12 @@ void ASTContext::InitBuiltinTypes() {
// nullptr type (C++0x 2.14.7)
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
+
+ // half type (OpenCL 6.1.1.1) / ARM NEON __fp16
+ InitBuiltinType(HalfTy, BuiltinType::Half);
}
-Diagnostic &ASTContext::getDiagnostics() const {
+DiagnosticsEngine &ASTContext::getDiagnostics() const {
return SourceMgr.getDiagnostics();
}
@@ -496,6 +534,24 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
= new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation);
}
+FunctionDecl *ASTContext::getClassScopeSpecializationPattern(
+ const FunctionDecl *FD){
+ assert(FD && "Specialization is 0");
+ llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos
+ = ClassScopeSpecializationPattern.find(FD);
+ if (Pos == ClassScopeSpecializationPattern.end())
+ return 0;
+
+ return Pos->second;
+}
+
+void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD,
+ FunctionDecl *Pattern) {
+ assert(FD && "Specialization is 0");
+ assert(Pattern && "Class scope specialization pattern is 0");
+ ClassScopeSpecializationPattern[FD] = Pattern;
+}
+
NamedDecl *
ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
@@ -555,35 +611,33 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst,
bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const {
return (FD->isBitField() && LastFD && !LastFD->isBitField() &&
- FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0);
-
+ FD->getBitWidthValue(*this) == 0);
}
bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const {
return (FD->isBitField() && LastFD && LastFD->isBitField() &&
- FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0 &&
- LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() != 0);
-
+ FD->getBitWidthValue(*this) == 0 &&
+ LastFD->getBitWidthValue(*this) != 0);
}
bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const {
return (FD->isBitField() && LastFD && LastFD->isBitField() &&
- FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() &&
- LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue());
+ FD->getBitWidthValue(*this) &&
+ LastFD->getBitWidthValue(*this));
}
-bool ASTContext::NoneBitfieldFollowsBitfield(const FieldDecl *FD,
+bool ASTContext::NonBitfieldFollowsBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const {
return (!FD->isBitField() && LastFD && LastFD->isBitField() &&
- LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue());
+ LastFD->getBitWidthValue(*this));
}
-bool ASTContext::BitfieldFollowsNoneBitfield(const FieldDecl *FD,
+bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD,
const FieldDecl *LastFD) const {
return (FD->isBitField() && LastFD && !LastFD->isBitField() &&
- FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue());
+ FD->getBitWidthValue(*this));
}
ASTContext::overridden_cxx_method_iterator
@@ -631,10 +685,11 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
const BuiltinType *BT = T->getAs<BuiltinType>();
assert(BT && "Not a floating point type!");
switch (BT->getKind()) {
- default: assert(0 && "Not a floating point type!");
- case BuiltinType::Float: return Target.getFloatFormat();
- case BuiltinType::Double: return Target.getDoubleFormat();
- case BuiltinType::LongDouble: return Target.getLongDoubleFormat();
+ default: llvm_unreachable("Not a floating point type!");
+ case BuiltinType::Half: return Target->getHalfFormat();
+ case BuiltinType::Float: return Target->getFloatFormat();
+ case BuiltinType::Double: return Target->getDoubleFormat();
+ case BuiltinType::LongDouble: return Target->getLongDoubleFormat();
}
}
@@ -644,7 +699,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
/// If @p RefAsPointee, references are treated like their underlying type
/// (for alignof), else they're treated like pointers (for CodeGen).
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
- unsigned Align = Target.getCharWidth();
+ unsigned Align = Target->getCharWidth();
bool UseAlignAttrOnly = false;
if (unsigned AlignFromAttr = D->getMaxAlignment()) {
@@ -654,7 +709,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
// *except* on a struct or struct member, where it only increases
// alignment unless 'packed' is also specified.
//
- // It is an error for [[align]] to decrease alignment, so we can
+ // It is an error for alignas to decrease alignment, so we can
// ignore that possibility; Sema should diagnose it.
if (isa<FieldDecl>(D)) {
UseAlignAttrOnly = D->hasAttr<PackedAttr>() ||
@@ -684,14 +739,14 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
if (!T->isIncompleteType() && !T->isFunctionType()) {
// Adjust alignments of declarations with array type by the
// large-array alignment on the target.
- unsigned MinWidth = Target.getLargeArrayMinWidth();
+ unsigned MinWidth = Target->getLargeArrayMinWidth();
const ArrayType *arrayType;
if (MinWidth && (arrayType = getAsArrayType(T))) {
if (isa<VariableArrayType>(arrayType))
- Align = std::max(Align, Target.getLargeArrayAlign());
+ Align = std::max(Align, Target->getLargeArrayAlign());
else if (isa<ConstantArrayType>(arrayType) &&
MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType)))
- Align = std::max(Align, Target.getLargeArrayAlign());
+ Align = std::max(Align, Target->getLargeArrayAlign());
// Walk through any array types while we're at it.
T = getBaseElementType(arrayType);
@@ -798,7 +853,7 @@ ASTContext::getTypeInfo(const Type *T) const {
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
- default: assert(0 && "Unknown builtin type!");
+ default: llvm_unreachable("Unknown builtin type!");
case BuiltinType::Void:
// GCC extension: alignof(void) = 8 bits.
Width = 0;
@@ -806,87 +861,91 @@ ASTContext::getTypeInfo(const Type *T) const {
break;
case BuiltinType::Bool:
- Width = Target.getBoolWidth();
- Align = Target.getBoolAlign();
+ Width = Target->getBoolWidth();
+ Align = Target->getBoolAlign();
break;
case BuiltinType::Char_S:
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::SChar:
- Width = Target.getCharWidth();
- Align = Target.getCharAlign();
+ Width = Target->getCharWidth();
+ Align = Target->getCharAlign();
break;
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
- Width = Target.getWCharWidth();
- Align = Target.getWCharAlign();
+ Width = Target->getWCharWidth();
+ Align = Target->getWCharAlign();
break;
case BuiltinType::Char16:
- Width = Target.getChar16Width();
- Align = Target.getChar16Align();
+ Width = Target->getChar16Width();
+ Align = Target->getChar16Align();
break;
case BuiltinType::Char32:
- Width = Target.getChar32Width();
- Align = Target.getChar32Align();
+ Width = Target->getChar32Width();
+ Align = Target->getChar32Align();
break;
case BuiltinType::UShort:
case BuiltinType::Short:
- Width = Target.getShortWidth();
- Align = Target.getShortAlign();
+ Width = Target->getShortWidth();
+ Align = Target->getShortAlign();
break;
case BuiltinType::UInt:
case BuiltinType::Int:
- Width = Target.getIntWidth();
- Align = Target.getIntAlign();
+ Width = Target->getIntWidth();
+ Align = Target->getIntAlign();
break;
case BuiltinType::ULong:
case BuiltinType::Long:
- Width = Target.getLongWidth();
- Align = Target.getLongAlign();
+ Width = Target->getLongWidth();
+ Align = Target->getLongAlign();
break;
case BuiltinType::ULongLong:
case BuiltinType::LongLong:
- Width = Target.getLongLongWidth();
- Align = Target.getLongLongAlign();
+ Width = Target->getLongLongWidth();
+ Align = Target->getLongLongAlign();
break;
case BuiltinType::Int128:
case BuiltinType::UInt128:
Width = 128;
Align = 128; // int128_t is 128-bit aligned on all targets.
break;
+ case BuiltinType::Half:
+ Width = Target->getHalfWidth();
+ Align = Target->getHalfAlign();
+ break;
case BuiltinType::Float:
- Width = Target.getFloatWidth();
- Align = Target.getFloatAlign();
+ Width = Target->getFloatWidth();
+ Align = Target->getFloatAlign();
break;
case BuiltinType::Double:
- Width = Target.getDoubleWidth();
- Align = Target.getDoubleAlign();
+ Width = Target->getDoubleWidth();
+ Align = Target->getDoubleAlign();
break;
case BuiltinType::LongDouble:
- Width = Target.getLongDoubleWidth();
- Align = Target.getLongDoubleAlign();
+ Width = Target->getLongDoubleWidth();
+ Align = Target->getLongDoubleAlign();
break;
case BuiltinType::NullPtr:
- Width = Target.getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)
- Align = Target.getPointerAlign(0); // == sizeof(void*)
+ Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)
+ Align = Target->getPointerAlign(0); // == sizeof(void*)
break;
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
- Width = Target.getPointerWidth(0);
- Align = Target.getPointerAlign(0);
+ Width = Target->getPointerWidth(0);
+ Align = Target->getPointerAlign(0);
break;
}
break;
case Type::ObjCObjectPointer:
- Width = Target.getPointerWidth(0);
- Align = Target.getPointerAlign(0);
+ Width = Target->getPointerWidth(0);
+ Align = Target->getPointerAlign(0);
break;
case Type::BlockPointer: {
unsigned AS = getTargetAddressSpace(
cast<BlockPointerType>(T)->getPointeeType());
- Width = Target.getPointerWidth(AS);
- Align = Target.getPointerAlign(AS);
+ Width = Target->getPointerWidth(AS);
+ Align = Target->getPointerAlign(AS);
break;
}
case Type::LValueReference:
@@ -895,14 +954,14 @@ ASTContext::getTypeInfo(const Type *T) const {
// the pointer route.
unsigned AS = getTargetAddressSpace(
cast<ReferenceType>(T)->getPointeeType());
- Width = Target.getPointerWidth(AS);
- Align = Target.getPointerAlign(AS);
+ Width = Target->getPointerWidth(AS);
+ Align = Target->getPointerAlign(AS);
break;
}
case Type::Pointer: {
unsigned AS = getTargetAddressSpace(cast<PointerType>(T)->getPointeeType());
- Width = Target.getPointerWidth(AS);
- Align = Target.getPointerAlign(AS);
+ Width = Target->getPointerWidth(AS);
+ Align = Target->getPointerAlign(AS);
break;
}
case Type::MemberPointer: {
@@ -1012,9 +1071,26 @@ ASTContext::getTypeInfo(const Type *T) const {
return getTypeInfo(getCanonicalType(T));
}
+ case Type::Atomic: {
+ std::pair<uint64_t, unsigned> Info
+ = getTypeInfo(cast<AtomicType>(T)->getValueType());
+ Width = Info.first;
+ Align = Info.second;
+ if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth() &&
+ llvm::isPowerOf2_64(Width)) {
+ // We can potentially perform lock-free atomic operations for this
+ // type; promote the alignment appropriately.
+ // FIXME: We could potentially promote the width here as well...
+ // is that worthwhile? (Non-struct atomic types generally have
+ // power-of-two size anyway, but structs might not. Requires a bit
+ // of implementation work to make sure we zero out the extra bits.)
+ Align = static_cast<unsigned>(Width);
+ }
+ }
+
}
- assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
+ assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
return std::make_pair(Width, Align);
}
@@ -1063,19 +1139,6 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
return ABIAlign;
}
-/// ShallowCollectObjCIvars -
-/// Collect all ivars, including those synthesized, in the current class.
-///
-void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const {
- // FIXME. This need be removed but there are two many places which
- // assume const-ness of ObjCInterfaceDecl
- ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
- for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
- Iv= Iv->getNextIvar())
- Ivars.push_back(Iv);
-}
-
/// DeepCollectObjCIvars -
/// This routine first collects all declared, but not synthesized, ivars in
/// super class and then collects all ivars, including those synthesized for
@@ -1084,17 +1147,16 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
///
void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
bool leafClass,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const {
+ SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const {
if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
DeepCollectObjCIvars(SuperClass, false, Ivars);
if (!leafClass) {
for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
E = OI->ivar_end(); I != E; ++I)
Ivars.push_back(*I);
- }
- else {
+ } else {
ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
- for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
+ for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
Iv= Iv->getNextIvar())
Ivars.push_back(Iv);
}
@@ -1562,7 +1624,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
// the target.
llvm::APInt ArySize(ArySizeIn);
ArySize =
- ArySize.zextOrTrunc(Target.getPointerWidth(getTargetAddressSpace(EltTy)));
+ ArySize.zextOrTrunc(Target->getPointerWidth(getTargetAddressSpace(EltTy)));
llvm::FoldingSetNodeID ID;
ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals);
@@ -1670,6 +1732,12 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
break;
}
+ case Type::Atomic: {
+ const AtomicType *at = cast<AtomicType>(ty);
+ result = getAtomicType(getVariableArrayDecayedType(at->getValueType()));
+ break;
+ }
+
case Type::ConstantArray: {
const ConstantArrayType *cat = cast<ConstantArrayType>(ty);
result = getConstantArrayType(
@@ -2026,7 +2094,7 @@ ASTContext::getFunctionType(QualType ResultTy,
// The exception spec is not part of the canonical type.
QualType Canonical;
if (!isCanonical || getCanonicalCallConv(CallConv) != CallConv) {
- llvm::SmallVector<QualType, 16> CanonicalArgs;
+ SmallVector<QualType, 16> CanonicalArgs;
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));
@@ -2322,7 +2390,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
unsigned NumArgs = Args.size();
- llvm::SmallVector<TemplateArgument, 4> ArgVec;
+ SmallVector<TemplateArgument, 4> ArgVec;
ArgVec.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
ArgVec.push_back(Args[i].getArgument());
@@ -2389,7 +2457,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
// Build the canonical template specialization type.
TemplateName CanonTemplate = getCanonicalTemplateName(Template);
- llvm::SmallVector<TemplateArgument, 4> CanonArgs;
+ SmallVector<TemplateArgument, 4> CanonArgs;
CanonArgs.reserve(NumArgs);
for (unsigned I = 0; I != NumArgs; ++I)
CanonArgs.push_back(getCanonicalTemplateArgument(Args[I]));
@@ -2509,7 +2577,7 @@ ASTContext::getDependentTemplateSpecializationType(
const IdentifierInfo *Name,
const TemplateArgumentListInfo &Args) const {
// TODO: avoid this copy
- llvm::SmallVector<TemplateArgument, 16> ArgCopy;
+ 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,
@@ -2543,7 +2611,7 @@ ASTContext::getDependentTemplateSpecializationType(
if (Keyword == ETK_None) CanonKeyword = ETK_Typename;
bool AnyNonCanonArgs = false;
- llvm::SmallVector<TemplateArgument, 16> CanonArgs(NumArgs);
+ SmallVector<TemplateArgument, 16> CanonArgs(NumArgs);
for (unsigned I = 0; I != NumArgs; ++I) {
CanonArgs[I] = getCanonicalTemplateArgument(Args[I]);
if (!CanonArgs[I].structurallyEquals(Args[I]))
@@ -2647,7 +2715,7 @@ QualType ASTContext::getObjCObjectType(QualType BaseType,
bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols);
if (!ProtocolsSorted || !BaseType.isCanonical()) {
if (!ProtocolsSorted) {
- llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
+ SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
Protocols + NumProtocols);
unsigned UniqueCount = NumProtocols;
@@ -2737,8 +2805,7 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const {
// typeof(expr) type. Use that as our canonical type.
toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr,
QualType((TypeOfExprType*)Canon, 0));
- }
- else {
+ } else {
// Build a new, canonical typeof(expr) type.
Canon
= new (*this, TypeAlignment) DependentTypeOfExprType(*this, tofExpr);
@@ -2821,8 +2888,7 @@ QualType ASTContext::getDecltypeType(Expr *e) const {
// decltype type. Use that as our canonical type.
dt = new (*this, TypeAlignment) DecltypeType(e, DependentTy,
QualType((DecltypeType*)Canon, 0));
- }
- else {
+ } else {
// Build a new, canonical typeof(expr) type.
Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e);
DependentDecltypeTypes.InsertNode(Canon, InsertPos);
@@ -2869,6 +2935,34 @@ QualType ASTContext::getAutoType(QualType DeducedType) const {
return QualType(AT, 0);
}
+/// getAtomicType - Return the uniqued reference to the atomic type for
+/// the given value type.
+QualType ASTContext::getAtomicType(QualType T) const {
+ // Unique pointers, to guarantee there is only one pointer of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ AtomicType::Profile(ID, T);
+
+ void *InsertPos = 0;
+ if (AtomicType *AT = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(AT, 0);
+
+ // If the atomic value type isn't canonical, this won't be a canonical type
+ // either, so fill in the canonical type field.
+ QualType Canonical;
+ if (!T.isCanonical()) {
+ Canonical = getAtomicType(getCanonicalType(T));
+
+ // Get the new insert position for the node we care about.
+ AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ }
+ AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical);
+ Types.push_back(New);
+ AtomicTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
/// getAutoDeductType - Get type pattern for deducing against 'auto'.
QualType ASTContext::getAutoDeductType() const {
if (AutoDeductTy.isNull())
@@ -2898,7 +2992,7 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) const {
/// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and
/// needs to agree with the definition in <stddef.h>.
CanQualType ASTContext::getSizeType() const {
- return getFromTargetType(Target.getSizeType());
+ return getFromTargetType(Target->getSizeType());
}
/// getSignedWCharType - Return the type of "signed wchar_t".
@@ -2918,7 +3012,7 @@ QualType ASTContext::getUnsignedWCharType() const {
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType ASTContext::getPointerDiffType() const {
- return getFromTargetType(Target.getPtrDiffType(0));
+ return getFromTargetType(Target->getPtrDiffType(0));
}
//===----------------------------------------------------------------------===//
@@ -3183,8 +3277,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
}
// Silence GCC warning
- assert(false && "Unhandled template argument kind");
- return TemplateArgument();
+ llvm_unreachable("Unhandled template argument kind");
}
NestedNameSpecifier *
@@ -3397,7 +3490,8 @@ static FloatingRank getFloatingRank(QualType T) {
assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type");
switch (T->getAs<BuiltinType>()->getKind()) {
- default: assert(0 && "getFloatingRank(): not a floating type");
+ default: llvm_unreachable("getFloatingRank(): not a floating type");
+ case BuiltinType::Half: return HalfRank;
case BuiltinType::Float: return FloatRank;
case BuiltinType::Double: return DoubleRank;
case BuiltinType::LongDouble: return LongDoubleRank;
@@ -3413,7 +3507,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
FloatingRank EltRank = getFloatingRank(Size);
if (Domain->isComplexType()) {
switch (EltRank) {
- default: assert(0 && "getFloatingRank(): illegal value for rank");
+ default: llvm_unreachable("getFloatingRank(): illegal value for rank");
case FloatRank: return FloatComplexTy;
case DoubleRank: return DoubleComplexTy;
case LongDoubleRank: return LongDoubleComplexTy;
@@ -3422,7 +3516,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
assert(Domain->isRealFloatingType() && "Unknown domain!");
switch (EltRank) {
- default: assert(0 && "getFloatingRank(): illegal value for rank");
+ default: llvm_unreachable("getFloatingRank(): illegal value for rank");
case FloatRank: return FloatTy;
case DoubleRank: return DoubleTy;
case LongDoubleRank: return LongDoubleTy;
@@ -3454,16 +3548,16 @@ unsigned ASTContext::getIntegerRank(const Type *T) const {
if (T->isSpecificBuiltinType(BuiltinType::WChar_S) ||
T->isSpecificBuiltinType(BuiltinType::WChar_U))
- T = getFromTargetType(Target.getWCharType()).getTypePtr();
+ T = getFromTargetType(Target->getWCharType()).getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Char16))
- T = getFromTargetType(Target.getChar16Type()).getTypePtr();
+ T = getFromTargetType(Target->getChar16Type()).getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Char32))
- T = getFromTargetType(Target.getChar32Type()).getTypePtr();
+ T = getFromTargetType(Target->getChar32Type()).getTypePtr();
switch (cast<BuiltinType>(T)->getKind()) {
- default: assert(0 && "getIntegerRank(): not a built-in integer");
+ default: llvm_unreachable("getIntegerRank(): not a built-in integer");
case BuiltinType::Bool:
return 1 + (getIntWidth(BoolTy) << 3);
case BuiltinType::Char_S:
@@ -3504,8 +3598,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
QualType FT = Field->getType();
- llvm::APSInt BitWidthAP = Field->getBitWidth()->EvaluateAsInt(*this);
- uint64_t BitWidth = BitWidthAP.getZExtValue();
+ uint64_t BitWidth = Field->getBitWidthValue(*this);
uint64_t IntSize = getTypeSize(IntTy);
// GCC extension compatibility: if the bit-field size is less than or equal
// to the size of int, it gets promoted no matter what its type is.
@@ -3653,82 +3746,6 @@ void ASTContext::setCFConstantStringType(QualType T) {
CFConstantStringTypeDecl = Rec->getDecl();
}
-// getNSConstantStringType - Return the type used for constant NSStrings.
-QualType ASTContext::getNSConstantStringType() const {
- if (!NSConstantStringTypeDecl) {
- NSConstantStringTypeDecl =
- CreateRecordDecl(*this, TTK_Struct, TUDecl,
- &Idents.get("__builtin_NSString"));
- NSConstantStringTypeDecl->startDefinition();
-
- QualType FieldTypes[3];
-
- // const int *isa;
- FieldTypes[0] = getPointerType(IntTy.withConst());
- // const char *str;
- FieldTypes[1] = getPointerType(CharTy.withConst());
- // unsigned int length;
- FieldTypes[2] = UnsignedIntTy;
-
- // Create fields
- for (unsigned i = 0; i < 3; ++i) {
- FieldDecl *Field = FieldDecl::Create(*this, NSConstantStringTypeDecl,
- SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
- /*Mutable=*/false,
- /*HasInit=*/false);
- Field->setAccess(AS_public);
- NSConstantStringTypeDecl->addDecl(Field);
- }
-
- NSConstantStringTypeDecl->completeDefinition();
- }
-
- return getTagDeclType(NSConstantStringTypeDecl);
-}
-
-void ASTContext::setNSConstantStringType(QualType T) {
- const RecordType *Rec = T->getAs<RecordType>();
- assert(Rec && "Invalid NSConstantStringType");
- NSConstantStringTypeDecl = Rec->getDecl();
-}
-
-QualType ASTContext::getObjCFastEnumerationStateType() const {
- if (!ObjCFastEnumerationStateTypeDecl) {
- ObjCFastEnumerationStateTypeDecl =
- CreateRecordDecl(*this, TTK_Struct, TUDecl,
- &Idents.get("__objcFastEnumerationState"));
- ObjCFastEnumerationStateTypeDecl->startDefinition();
-
- QualType FieldTypes[] = {
- UnsignedLongTy,
- getPointerType(ObjCIdTypedefType),
- getPointerType(UnsignedLongTy),
- getConstantArrayType(UnsignedLongTy,
- llvm::APInt(32, 5), ArrayType::Normal, 0)
- };
-
- for (size_t i = 0; i < 4; ++i) {
- FieldDecl *Field = FieldDecl::Create(*this,
- ObjCFastEnumerationStateTypeDecl,
- SourceLocation(),
- SourceLocation(), 0,
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0,
- /*Mutable=*/false,
- /*HasInit=*/false);
- Field->setAccess(AS_public);
- ObjCFastEnumerationStateTypeDecl->addDecl(Field);
- }
-
- ObjCFastEnumerationStateTypeDecl->completeDefinition();
- }
-
- return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
-}
-
QualType ASTContext::getBlockDescriptorType() const {
if (BlockDescriptorType)
return getTagDeclType(BlockDescriptorType);
@@ -3768,12 +3785,6 @@ QualType ASTContext::getBlockDescriptorType() const {
return getTagDeclType(BlockDescriptorType);
}
-void ASTContext::setBlockDescriptorType(QualType T) {
- const RecordType *Rec = T->getAs<RecordType>();
- assert(Rec && "Invalid BlockDescriptorType");
- BlockDescriptorType = Rec->getDecl();
-}
-
QualType ASTContext::getBlockDescriptorExtendedType() const {
if (BlockDescriptorExtendedType)
return getTagDeclType(BlockDescriptorExtendedType);
@@ -3817,12 +3828,6 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
return getTagDeclType(BlockDescriptorExtendedType);
}
-void ASTContext::setBlockDescriptorExtendedType(QualType T) {
- const RecordType *Rec = T->getAs<RecordType>();
- assert(Rec && "Invalid BlockDescriptorType");
- BlockDescriptorExtendedType = Rec->getDecl();
-}
-
bool ASTContext::BlockRequiresCopying(QualType Ty) const {
if (Ty->isObjCRetainableType())
return true;
@@ -3837,7 +3842,7 @@ bool ASTContext::BlockRequiresCopying(QualType Ty) const {
}
QualType
-ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const {
+ASTContext::BuildByRefType(StringRef DeclName, QualType Ty) const {
// type = struct __Block_byref_1_X {
// void *__isa;
// struct __Block_byref_1_X *__forwarding;
@@ -3869,7 +3874,7 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const {
Ty
};
- llvm::StringRef FieldNames[] = {
+ StringRef FieldNames[] = {
"__isa",
"__forwarding",
"__flags",
@@ -3897,10 +3902,15 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const {
return getPointerType(getTagDeclType(T));
}
-void ASTContext::setObjCFastEnumerationStateType(QualType T) {
- const RecordType *Rec = T->getAs<RecordType>();
- assert(Rec && "Invalid ObjCFAstEnumerationStateType");
- ObjCFastEnumerationStateTypeDecl = Rec->getDecl();
+TypedefDecl *ASTContext::getObjCInstanceTypeDecl() {
+ if (!ObjCInstanceTypeDecl)
+ ObjCInstanceTypeDecl = TypedefDecl::Create(*this,
+ getTranslationUnitDecl(),
+ SourceLocation(),
+ SourceLocation(),
+ &Idents.get("instancetype"),
+ getTrivialTypeSourceInfo(getObjCIdType()));
+ return ObjCInstanceTypeDecl;
}
// This returns true if a type has been typedefed to BOOL:
@@ -3962,7 +3972,6 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
S += charUnitsToString(ParmOffset);
// Block pointer and offset.
S += "@?0";
- ParmOffset = PtrSize;
// Argument types.
ParmOffset = PtrSize;
@@ -4044,7 +4053,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
// The first two arguments (self and _cmd) are pointers; account for
// their size.
CharUnits ParmOffset = 2 * PtrSize;
- for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator PI = Decl->param_begin(),
E = Decl->sel_param_end(); PI != E; ++PI) {
QualType PType = (*PI)->getType();
CharUnits sz = getObjCEncodingTypeSize(PType);
@@ -4061,9 +4070,9 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
// Argument types.
ParmOffset = 2 * PtrSize;
- for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator PI = Decl->param_begin(),
E = Decl->sel_param_end(); PI != E; ++PI) {
- ParmVarDecl *PVDecl = *PI;
+ const ParmVarDecl *PVDecl = *PI;
QualType PType = PVDecl->getOriginalType();
if (const ArrayType *AT =
dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
@@ -4166,6 +4175,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
case ObjCPropertyDecl::Assign: break;
case ObjCPropertyDecl::Copy: S += ",C"; break;
case ObjCPropertyDecl::Retain: S += ",&"; break;
+ case ObjCPropertyDecl::Weak: S += ",W"; break;
}
}
@@ -4225,7 +4235,7 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) {
switch (T->getAs<BuiltinType>()->getKind()) {
- default: assert(0 && "Unhandled builtin type kind");
+ default: llvm_unreachable("Unhandled builtin type kind");
case BuiltinType::Void: return 'v';
case BuiltinType::Bool: return 'B';
case BuiltinType::Char_U:
@@ -4252,10 +4262,20 @@ static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) {
}
}
+static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) {
+ EnumDecl *Enum = ET->getDecl();
+
+ // The encoding of an non-fixed enum type is always 'i', regardless of size.
+ if (!Enum->isFixed())
+ return 'i';
+
+ // The encoding of a fixed enum type matches its fixed underlying type.
+ return ObjCEncodingForPrimitiveKind(C, Enum->getIntegerType());
+}
+
static void EncodeBitField(const ASTContext *Ctx, std::string& S,
QualType T, const FieldDecl *FD) {
- const Expr *E = FD->getBitWidth();
- assert(E && "bitfield width not there - getObjCEncodingForTypeImpl");
+ assert(FD->isBitField() && "not a bitfield - getObjCEncodingForTypeImpl");
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,
@@ -4276,13 +4296,12 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S,
const RecordDecl *RD = FD->getParent();
const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex()));
- if (T->isEnumeralType())
- S += 'i';
+ if (const EnumType *ET = T->getAs<EnumType>())
+ S += ObjCEncodingForEnumType(Ctx, ET);
else
S += ObjCEncodingForPrimitiveKind(Ctx, T);
}
- unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue();
- S += llvm::utostr(N);
+ S += llvm::utostr(FD->getBitWidthValue(*Ctx));
}
// FIXME: Use SmallString for accumulating string.
@@ -4342,7 +4361,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
// Another legacy compatibility encoding. Some ObjC qualifier and type
// combinations need to be rearranged.
// Rewrite "in const" from "nr" to "rn"
- if (llvm::StringRef(S).endswith("nr"))
+ if (StringRef(S).endswith("nr"))
S.replace(S.end()-2, S.end(), "rn");
}
@@ -4423,7 +4442,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
= TemplateSpecializationType::PrintTemplateArgumentList(
TemplateArgs.data(),
TemplateArgs.size(),
- (*this).PrintingPolicy);
+ (*this).getPrintingPolicy());
S += TemplateArgsStr;
}
@@ -4463,11 +4482,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
return;
}
- if (T->isEnumeralType()) {
+ if (const EnumType *ET = T->getAs<EnumType>()) {
if (FD && FD->isBitField())
EncodeBitField(this, S, T, FD);
else
- S += 'i';
+ S += ObjCEncodingForEnumType(this, ET);
return;
}
@@ -4487,10 +4506,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
const IdentifierInfo *II = OI->getIdentifier();
S += II->getName();
S += '=';
- llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+ SmallVector<const ObjCIvarDecl*, 32> Ivars;
DeepCollectObjCIvars(OI, true, Ivars);
for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
- FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
+ const FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
if (Field->isBitField())
getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
else
@@ -4573,7 +4592,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
return;
}
- assert(0 && "@encode for type not implemented!");
+ llvm_unreachable("@encode for type not implemented!");
}
void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
@@ -4621,8 +4640,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
if (base->isEmpty())
continue;
uint64_t offs = layout.getVBaseClassOffsetInBits(base);
- FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
- std::make_pair(offs, base));
+ if (FieldOrBaseOffsets.find(offs) == FieldOrBaseOffsets.end())
+ FieldOrBaseOffsets.insert(FieldOrBaseOffsets.end(),
+ std::make_pair(offs, base));
}
}
@@ -4637,7 +4657,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
std::multimap<uint64_t, NamedDecl *>::iterator
CurLayObj = FieldOrBaseOffsets.begin();
- if (CurLayObj != FieldOrBaseOffsets.end() && CurLayObj->first != 0) {
+ if ((CurLayObj != FieldOrBaseOffsets.end() && CurLayObj->first != 0) ||
+ (CurLayObj == FieldOrBaseOffsets.end() &&
+ CXXRec && CXXRec->isDynamicClass())) {
assert(CXXRec && CXXRec->isDynamicClass() &&
"Offset 0 was empty but no VTable ?");
if (FD) {
@@ -4695,7 +4717,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
if (field->isBitField()) {
EncodeBitField(this, S, field->getType(), field);
- CurOffs += field->getBitWidth()->EvaluateAsInt(*this).getZExtValue();
+ CurOffs += field->getBitWidthValue(*this);
} else {
QualType qt = field->getType();
getLegacyIntegralTypeEncoding(qt);
@@ -4731,20 +4753,48 @@ void ASTContext::setBuiltinVaListType(QualType T) {
BuiltinVaListType = T;
}
-void ASTContext::setObjCIdType(QualType T) {
- ObjCIdTypedefType = T;
+TypedefDecl *ASTContext::getObjCIdDecl() const {
+ if (!ObjCIdDecl) {
+ QualType T = getObjCObjectType(ObjCBuiltinIdTy, 0, 0);
+ T = getObjCObjectPointerType(T);
+ TypeSourceInfo *IdInfo = getTrivialTypeSourceInfo(T);
+ ObjCIdDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
+ getTranslationUnitDecl(),
+ SourceLocation(), SourceLocation(),
+ &Idents.get("id"), IdInfo);
+ }
+
+ return ObjCIdDecl;
}
-void ASTContext::setObjCSelType(QualType T) {
- ObjCSelTypedefType = T;
+TypedefDecl *ASTContext::getObjCSelDecl() const {
+ if (!ObjCSelDecl) {
+ QualType SelT = getPointerType(ObjCBuiltinSelTy);
+ TypeSourceInfo *SelInfo = getTrivialTypeSourceInfo(SelT);
+ ObjCSelDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
+ getTranslationUnitDecl(),
+ SourceLocation(), SourceLocation(),
+ &Idents.get("SEL"), SelInfo);
+ }
+ return ObjCSelDecl;
}
void ASTContext::setObjCProtoType(QualType QT) {
ObjCProtoType = QT;
}
-void ASTContext::setObjCClassType(QualType T) {
- ObjCClassTypedefType = T;
+TypedefDecl *ASTContext::getObjCClassDecl() const {
+ if (!ObjCClassDecl) {
+ QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0);
+ T = getObjCObjectPointerType(T);
+ TypeSourceInfo *ClassInfo = getTrivialTypeSourceInfo(T);
+ ObjCClassDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
+ getTranslationUnitDecl(),
+ SourceLocation(), SourceLocation(),
+ &Idents.get("Class"), ClassInfo);
+ }
+
+ return ObjCClassDecl;
}
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
@@ -4925,8 +4975,7 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const {
case TargetInfo::UnsignedLongLong: return UnsignedLongLongTy;
}
- assert(false && "Unhandled TargetInfo::IntType value");
- return CanQualType();
+ llvm_unreachable("Unhandled TargetInfo::IntType value");
}
//===----------------------------------------------------------------------===//
@@ -4937,7 +4986,7 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const {
/// garbage collection attribute.
///
Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const {
- if (getLangOptions().getGCMode() == LangOptions::NonGC)
+ if (getLangOptions().getGC() == LangOptions::NonGC)
return Qualifiers::GCNone;
assert(getLangOptions().ObjC1);
@@ -5261,7 +5310,7 @@ static
void getIntersectionOfProtocols(ASTContext &Context,
const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT,
- llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
+ SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
const ObjCObjectType* LHS = LHSOPT->getObjectType();
const ObjCObjectType* RHS = RHSOPT->getObjectType();
@@ -5287,8 +5336,7 @@ void getIntersectionOfProtocols(ASTContext &Context,
for (unsigned i = 0; i < RHSNumProtocols; ++i)
if (InheritedProtocolSet.count(RHSProtocols[i]))
IntersectionOfProtocols.push_back(RHSProtocols[i]);
- }
- else {
+ } else {
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
Context.CollectInheritedProtocols(RHS->getInterface(),
RHSInheritedProtocols);
@@ -5317,7 +5365,7 @@ QualType ASTContext::areCommonBaseCompatible(
do {
LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl));
if (canAssignObjCInterfaces(LHS, RHS)) {
- llvm::SmallVector<ObjCProtocolDecl *, 8> Protocols;
+ SmallVector<ObjCProtocolDecl *, 8> Protocols;
getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols);
QualType Result = QualType(LHS, 0);
@@ -5552,13 +5600,13 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult())
return QualType();
- // It's noreturn if either type is.
- // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
- bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
- if (NoReturn != lbaseInfo.getNoReturn())
+ // functypes which return are preferred over those that do not.
+ if (lbaseInfo.getNoReturn() && !rbaseInfo.getNoReturn())
allLTypes = false;
- if (NoReturn != rbaseInfo.getNoReturn())
+ else if (!lbaseInfo.getNoReturn() && rbaseInfo.getNoReturn())
allRTypes = false;
+ // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
+ bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn);
@@ -5579,8 +5627,12 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (lproto->getTypeQuals() != rproto->getTypeQuals())
return QualType();
+ if (LangOpts.ObjCAutoRefCount &&
+ !FunctionTypesMatchOnNSConsumedAttrs(rproto, lproto))
+ return QualType();
+
// Check argument compatibility
- llvm::SmallVector<QualType, 10> types;
+ SmallVector<QualType, 10> types;
for (unsigned i = 0; i < lproto_nargs; i++) {
QualType largtype = lproto->getArgType(i).getUnqualifiedType();
QualType rargtype = rproto->getArgType(i).getUnqualifiedType();
@@ -5603,6 +5655,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (getCanonicalType(argtype) != getCanonicalType(rargtype))
allRTypes = false;
}
+
if (allLTypes) return lhs;
if (allRTypes) return rhs;
@@ -5756,22 +5809,19 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
- assert(false && "Non-canonical and dependent types shouldn't get here");
- return QualType();
+ llvm_unreachable("Non-canonical and dependent types shouldn't get here");
case Type::LValueReference:
case Type::RValueReference:
case Type::MemberPointer:
- assert(false && "C++ should never be in mergeTypes");
- return QualType();
+ llvm_unreachable("C++ should never be in mergeTypes");
case Type::ObjCInterface:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::FunctionProto:
case Type::ExtVector:
- assert(false && "Types are eliminated above");
- return QualType();
+ llvm_unreachable("Types are eliminated above");
case Type::Pointer:
{
@@ -5809,6 +5859,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return RHS;
return getBlockPointerType(ResultType);
}
+ case Type::Atomic:
+ {
+ // Merge two pointer types, while trying to preserve typedef info
+ QualType LHSValue = LHS->getAs<AtomicType>()->getValueType();
+ QualType RHSValue = RHS->getAs<AtomicType>()->getValueType();
+ if (Unqualified) {
+ LHSValue = LHSValue.getUnqualifiedType();
+ RHSValue = RHSValue.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
+ Unqualified);
+ if (ResultType.isNull()) return QualType();
+ if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
+ return LHS;
+ if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
+ return RHS;
+ return getAtomicType(ResultType);
+ }
case Type::ConstantArray:
{
const ConstantArrayType* LCAT = getAsConstantArrayType(LHS);
@@ -5904,6 +5972,26 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return QualType();
}
+bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs(
+ const FunctionProtoType *FromFunctionType,
+ const FunctionProtoType *ToFunctionType) {
+ if (FromFunctionType->hasAnyConsumedArgs() !=
+ ToFunctionType->hasAnyConsumedArgs())
+ return false;
+ FunctionProtoType::ExtProtoInfo FromEPI =
+ FromFunctionType->getExtProtoInfo();
+ FunctionProtoType::ExtProtoInfo ToEPI =
+ ToFunctionType->getExtProtoInfo();
+ if (FromEPI.ConsumedArguments && ToEPI.ConsumedArguments)
+ for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+ ArgIdx != NumArgs; ++ArgIdx) {
+ if (FromEPI.ConsumedArguments[ArgIdx] !=
+ ToEPI.ConsumedArguments[ArgIdx])
+ return false;
+ }
+ return true;
+}
+
/// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and
/// 'RHS' attributes and returns the merged version; including for function
/// return types.
@@ -6022,8 +6110,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
case BuiltinType::Int128:
return UnsignedInt128Ty;
default:
- assert(0 && "Unexpected signed integer type");
- return QualType();
+ llvm_unreachable("Unexpected signed integer type");
}
}
@@ -6080,7 +6167,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
// Read the base type.
switch (*Str++) {
- default: assert(0 && "Unknown builtin type letter!");
+ default: llvm_unreachable("Unknown builtin type letter!");
case 'v':
assert(HowLong == 0 && !Signed && !Unsigned &&
"Bad modifiers used with 'v'!");
@@ -6183,7 +6270,11 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
assert(!RequiresICE && "Can't require complex ICE");
Type = Context.getComplexType(ElementType);
break;
- }
+ }
+ case 'Y' : {
+ Type = Context.getPointerDiffType();
+ break;
+ }
case 'P':
Type = Context.getFILEType();
if (Type.isNull()) {
@@ -6247,7 +6338,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
unsigned *IntegerConstantArgs) const {
const char *TypeStr = BuiltinInfo.GetTypeString(Id);
- llvm::SmallVector<QualType, 8> ArgTypes;
+ SmallVector<QualType, 8> ArgTypes;
bool RequiresICE = false;
Error = GE_None;
@@ -6405,7 +6496,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// Forward declarations aren't required.
if (!FD->doesThisDeclarationHaveABody())
- return false;
+ return FD->doesDeclarationForceExternallyVisibleDefinition();
// Constructors and destructors are required.
if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
@@ -6431,7 +6522,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;
return true;
}
-
+
const VarDecl *VD = cast<VarDecl>(D);
assert(VD->isFileVarDecl() && "Expected file scoped var");
@@ -6472,30 +6563,42 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
}
MangleContext *ASTContext::createMangleContext() {
- switch (Target.getCXXABI()) {
+ switch (Target->getCXXABI()) {
case CXXABI_ARM:
case CXXABI_Itanium:
return createItaniumMangleContext(*this, getDiagnostics());
case CXXABI_Microsoft:
return createMicrosoftMangleContext(*this, getDiagnostics());
}
- assert(0 && "Unsupported ABI");
- return 0;
+ llvm_unreachable("Unsupported ABI");
}
CXXABI::~CXXABI() {}
size_t ASTContext::getSideTableAllocatedMemory() const {
- size_t bytes = 0;
- bytes += ASTRecordLayouts.getMemorySize();
- bytes += ObjCLayouts.getMemorySize();
- bytes += KeyFunctions.getMemorySize();
- bytes += ObjCImpls.getMemorySize();
- bytes += BlockVarCopyInits.getMemorySize();
- bytes += DeclAttrs.getMemorySize();
- bytes += InstantiatedFromStaticDataMember.getMemorySize();
- bytes += InstantiatedFromUsingDecl.getMemorySize();
- bytes += InstantiatedFromUsingShadowDecl.getMemorySize();
- bytes += InstantiatedFromUnnamedFieldDecl.getMemorySize();
- return bytes;
+ return ASTRecordLayouts.getMemorySize()
+ + llvm::capacity_in_bytes(ObjCLayouts)
+ + llvm::capacity_in_bytes(KeyFunctions)
+ + llvm::capacity_in_bytes(ObjCImpls)
+ + llvm::capacity_in_bytes(BlockVarCopyInits)
+ + llvm::capacity_in_bytes(DeclAttrs)
+ + llvm::capacity_in_bytes(InstantiatedFromStaticDataMember)
+ + llvm::capacity_in_bytes(InstantiatedFromUsingDecl)
+ + llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl)
+ + llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl)
+ + llvm::capacity_in_bytes(OverriddenMethods)
+ + llvm::capacity_in_bytes(Types)
+ + llvm::capacity_in_bytes(VariableArrayTypes)
+ + llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
+}
+
+void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
+ ParamIndices[D] = index;
+}
+
+unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const {
+ ParameterIndexTable::const_iterator I = ParamIndices.find(D);
+ assert(I != ParamIndices.end() &&
+ "ParmIndices lacks entry set by ParmVarDecl");
+ return I->second;
}
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 7c91b5cb7a00..07820dc3cc56 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -152,16 +152,16 @@ break; \
/// diagnostic message
static std::string
ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
- const Diagnostic::ArgumentValue *PrevArgs,
+ const DiagnosticsEngine::ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
- llvm::SmallVectorImpl<intptr_t> &QualTypeVals) {
+ SmallVectorImpl<intptr_t> &QualTypeVals) {
// FIXME: Playing with std::string is really slow.
bool ForceAKA = false;
QualType CanTy = Ty.getCanonicalType();
- std::string S = Ty.getAsString(Context.PrintingPolicy);
- std::string CanS = CanTy.getAsString(Context.PrintingPolicy);
+ std::string S = Ty.getAsString(Context.getPrintingPolicy());
+ std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());
- for (llvm::SmallVectorImpl<intptr_t>::iterator I = QualTypeVals.begin(),
+ for (SmallVectorImpl<intptr_t>::iterator I = QualTypeVals.begin(),
E = QualTypeVals.end(); I != E; ++I) {
QualType CompareTy =
QualType::getFromOpaquePtr(reinterpret_cast<void*>(*I));
@@ -170,10 +170,10 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
QualType CompareCanTy = CompareTy.getCanonicalType();
if (CompareCanTy == CanTy)
continue; // Same canonical types
- std::string CompareS = CompareTy.getAsString(Context.PrintingPolicy);
+ std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
if (CompareS != S)
continue; // Original strings are different
- std::string CompareCanS = CompareCanTy.getAsString(Context.PrintingPolicy);
+ std::string CompareCanS = CompareCanTy.getAsString(Context.getPrintingPolicy());
if (CompareCanS == CanS)
continue; // No new info from canonical type
@@ -186,7 +186,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
bool Repeated = false;
for (unsigned i = 0; i != NumPrevArgs; ++i) {
// TODO: Handle ak_declcontext case.
- if (PrevArgs[i].first == Diagnostic::ak_qualtype) {
+ if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) {
void *Ptr = (void*)PrevArgs[i].second;
QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
if (PrevTy == Ty) {
@@ -205,7 +205,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
if (DesugaredTy == Ty) {
DesugaredTy = Ty.getCanonicalType();
}
- std::string akaStr = DesugaredTy.getAsString(Context.PrintingPolicy);
+ std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy());
if (akaStr != S) {
S = "'" + S + "' (aka '" + akaStr + "')";
return S;
@@ -218,25 +218,25 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
}
void clang::FormatASTNodeDiagnosticArgument(
- Diagnostic::ArgumentKind Kind,
+ DiagnosticsEngine::ArgumentKind Kind,
intptr_t Val,
const char *Modifier,
unsigned ModLen,
const char *Argument,
unsigned ArgLen,
- const Diagnostic::ArgumentValue *PrevArgs,
+ const DiagnosticsEngine::ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
- llvm::SmallVectorImpl<char> &Output,
+ SmallVectorImpl<char> &Output,
void *Cookie,
- llvm::SmallVectorImpl<intptr_t> &QualTypeVals) {
+ SmallVectorImpl<intptr_t> &QualTypeVals) {
ASTContext &Context = *static_cast<ASTContext*>(Cookie);
std::string S;
bool NeedQuotes = true;
switch (Kind) {
- default: assert(0 && "unknown ArgumentKind");
- case Diagnostic::ak_qualtype: {
+ default: llvm_unreachable("unknown ArgumentKind");
+ case DiagnosticsEngine::ak_qualtype: {
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for QualType argument");
@@ -246,7 +246,7 @@ void clang::FormatASTNodeDiagnosticArgument(
NeedQuotes = false;
break;
}
- case Diagnostic::ak_declarationname: {
+ case DiagnosticsEngine::ak_declarationname: {
DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
S = N.getAsString();
@@ -260,7 +260,7 @@ void clang::FormatASTNodeDiagnosticArgument(
"Invalid modifier for DeclarationName argument");
break;
}
- case Diagnostic::ak_nameddecl: {
+ case DiagnosticsEngine::ak_nameddecl: {
bool Qualified;
if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
Qualified = true;
@@ -269,18 +269,18 @@ void clang::FormatASTNodeDiagnosticArgument(
"Invalid modifier for NamedDecl* argument");
Qualified = false;
}
- reinterpret_cast<NamedDecl*>(Val)->
- getNameForDiagnostic(S, Context.PrintingPolicy, Qualified);
+ const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val);
+ ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), Qualified);
break;
}
- case Diagnostic::ak_nestednamespec: {
+ case DiagnosticsEngine::ak_nestednamespec: {
llvm::raw_string_ostream OS(S);
reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS,
- Context.PrintingPolicy);
+ Context.getPrintingPolicy());
NeedQuotes = false;
break;
}
- case Diagnostic::ak_declcontext: {
+ case DiagnosticsEngine::ak_declcontext: {
DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
assert(DC && "Should never have a null declaration context");
@@ -305,7 +305,7 @@ void clang::FormatASTNodeDiagnosticArgument(
S += "function ";
S += "'";
- ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);
+ ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), true);
S += "'";
}
NeedQuotes = false;
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index f5e392f88d0b..af66b04c3ad7 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -59,6 +59,7 @@ namespace {
QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T);
QualType VisitFunctionProtoType(const FunctionProtoType *T);
// FIXME: UnresolvedUsingType
+ QualType VisitParenType(const ParenType *T);
QualType VisitTypedefType(const TypedefType *T);
QualType VisitTypeOfExprType(const TypeOfExprType *T);
// FIXME: DependentTypeOfExprType
@@ -83,16 +84,20 @@ namespace {
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
SourceLocation &Loc);
+ void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = 0);
void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
- bool ImportDefinition(RecordDecl *From, RecordDecl *To);
+ bool ImportDefinition(RecordDecl *From, RecordDecl *To,
+ bool ForceImport = false);
+ bool ImportDefinition(EnumDecl *From, EnumDecl *To,
+ bool ForceImport = false);
TemplateParameterList *ImportTemplateParameterList(
TemplateParameterList *Params);
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
- llvm::SmallVectorImpl<TemplateArgument> &ToArgs);
+ SmallVectorImpl<TemplateArgument> &ToArgs);
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord);
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
@@ -805,12 +810,74 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
break;
}
-
+
+ case Type::Atomic: {
+ if (!IsStructurallyEquivalent(Context,
+ cast<AtomicType>(T1)->getValueType(),
+ cast<AtomicType>(T2)->getValueType()))
+ return false;
+ break;
+ }
+
} // end switch
return true;
}
+/// \brief Determine structural equivalence of two fields.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ FieldDecl *Field1, FieldDecl *Field2) {
+ RecordDecl *Owner2 = cast<RecordDecl>(Field2->getDeclContext());
+
+ if (!IsStructurallyEquivalent(Context,
+ Field1->getType(), Field2->getType())) {
+ Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(Owner2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_field)
+ << Field2->getDeclName() << Field2->getType();
+ Context.Diag1(Field1->getLocation(), diag::note_odr_field)
+ << Field1->getDeclName() << Field1->getType();
+ return false;
+ }
+
+ if (Field1->isBitField() != Field2->isBitField()) {
+ Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(Owner2);
+ if (Field1->isBitField()) {
+ Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
+ << Field1->getDeclName() << Field1->getType()
+ << Field1->getBitWidthValue(Context.C1);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field)
+ << Field2->getDeclName();
+ } else {
+ Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
+ << Field2->getDeclName() << Field2->getType()
+ << Field2->getBitWidthValue(Context.C2);
+ Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field)
+ << Field1->getDeclName();
+ }
+ return false;
+ }
+
+ if (Field1->isBitField()) {
+ // Make sure that the bit-fields are the same length.
+ unsigned Bits1 = Field1->getBitWidthValue(Context.C1);
+ unsigned Bits2 = Field2->getBitWidthValue(Context.C2);
+
+ if (Bits1 != Bits2) {
+ Context.Diag2(Owner2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(Owner2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
+ << Field2->getDeclName() << Field2->getType() << Bits2;
+ Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
+ << Field1->getDeclName() << Field1->getType() << Bits1;
+ return false;
+ }
+ }
+
+ return true;
+}
+
/// \brief Determine structural equivalence of two records.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
RecordDecl *D1, RecordDecl *D2) {
@@ -928,61 +995,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
}
- if (!IsStructurallyEquivalent(Context,
- Field1->getType(), Field2->getType())) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_field)
- << Field2->getDeclName() << Field2->getType();
- Context.Diag1(Field1->getLocation(), diag::note_odr_field)
- << Field1->getDeclName() << Field1->getType();
- return false;
- }
-
- if (Field1->isBitField() != Field2->isBitField()) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- if (Field1->isBitField()) {
- llvm::APSInt Bits;
- Field1->getBitWidth()->isIntegerConstantExpr(Bits, Context.C1);
- Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
- << Field1->getDeclName() << Field1->getType()
- << Bits.toString(10, false);
- Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field)
- << Field2->getDeclName();
- } else {
- llvm::APSInt Bits;
- Field2->getBitWidth()->isIntegerConstantExpr(Bits, Context.C2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
- << Field2->getDeclName() << Field2->getType()
- << Bits.toString(10, false);
- Context.Diag1(Field1->getLocation(),
- diag::note_odr_not_bit_field)
- << Field1->getDeclName();
- }
- return false;
- }
-
- if (Field1->isBitField()) {
- // Make sure that the bit-fields are the same length.
- llvm::APSInt Bits1, Bits2;
- if (!Field1->getBitWidth()->isIntegerConstantExpr(Bits1, Context.C1))
- return false;
- if (!Field2->getBitWidth()->isIntegerConstantExpr(Bits2, Context.C2))
- return false;
-
- if (!IsSameValue(Bits1, Bits2)) {
- Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
- << Context.C2.getTypeDeclType(D2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
- << Field2->getDeclName() << Field2->getType()
- << Bits2.toString(10, false);
- Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
- << Field1->getDeclName() << Field1->getType()
- << Bits1.toString(10, false);
- return false;
- }
- }
+ if (!IsStructurallyEquivalent(Context, *Field1, *Field2))
+ return false;
}
if (Field2 != Field2End) {
@@ -1360,6 +1374,7 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
case BuiltinType::Long : return Importer.getToContext().LongTy;
case BuiltinType::LongLong : return Importer.getToContext().LongLongTy;
case BuiltinType::Int128 : return Importer.getToContext().Int128Ty;
+ case BuiltinType::Half: return Importer.getToContext().HalfTy;
case BuiltinType::Float: return Importer.getToContext().FloatTy;
case BuiltinType::Double: return Importer.getToContext().DoubleTy;
case BuiltinType::LongDouble: return Importer.getToContext().LongDoubleTy;
@@ -1518,7 +1533,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
return QualType();
// Import argument types
- llvm::SmallVector<QualType, 4> ArgTypes;
+ SmallVector<QualType, 4> ArgTypes;
for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
AEnd = T->arg_type_end();
A != AEnd; ++A) {
@@ -1529,7 +1544,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
}
// Import exception types
- llvm::SmallVector<QualType, 4> ExceptionTypes;
+ SmallVector<QualType, 4> ExceptionTypes;
for (FunctionProtoType::exception_iterator E = T->exception_begin(),
EEnd = T->exception_end();
E != EEnd; ++E) {
@@ -1546,6 +1561,14 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
ArgTypes.size(), EPI);
}
+QualType ASTNodeImporter::VisitParenType(const ParenType *T) {
+ QualType ToInnerType = Importer.Import(T->getInnerType());
+ if (ToInnerType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getParenType(ToInnerType);
+}
+
QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
TypedefNameDecl *ToDecl
= dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl()));
@@ -1628,7 +1651,7 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType(
if (ToTemplate.isNull())
return QualType();
- llvm::SmallVector<TemplateArgument, 2> ToTemplateArgs;
+ SmallVector<TemplateArgument, 2> ToTemplateArgs;
if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToTemplateArgs))
return QualType();
@@ -1677,7 +1700,7 @@ QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
if (ToBaseType.isNull())
return QualType();
- llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ SmallVector<ObjCProtocolDecl *, 4> Protocols;
for (ObjCObjectType::qual_iterator P = T->qual_begin(),
PEnd = T->qual_end();
P != PEnd; ++P) {
@@ -1731,6 +1754,35 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
return false;
}
+void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) {
+ if (!FromD)
+ return;
+
+ if (!ToD) {
+ ToD = Importer.Import(FromD);
+ if (!ToD)
+ return;
+ }
+
+ if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) {
+ if (RecordDecl *ToRecord = cast_or_null<RecordDecl>(ToD)) {
+ if (FromRecord->getDefinition() && !ToRecord->getDefinition()) {
+ ImportDefinition(FromRecord, ToRecord);
+ }
+ }
+ return;
+ }
+
+ if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) {
+ if (EnumDecl *ToEnum = cast_or_null<EnumDecl>(ToD)) {
+ if (FromEnum->getDefinition() && !ToEnum->getDefinition()) {
+ ImportDefinition(FromEnum, ToEnum);
+ }
+ }
+ return;
+ }
+}
+
void
ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
DeclarationNameInfo& To) {
@@ -1761,16 +1813,13 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
To.setNamedTypeInfo(Importer.Import(FromTInfo));
return;
}
- assert(0 && "Unknown name kind.");
+ llvm_unreachable("Unknown name kind.");
}
}
void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
if (Importer.isMinimalImport() && !ForceImport) {
- if (DeclContext *ToDC = Importer.ImportContext(FromDC)) {
- ToDC->setHasExternalLexicalStorage();
- ToDC->setHasExternalVisibleStorage();
- }
+ Importer.ImportContext(FromDC);
return;
}
@@ -1781,8 +1830,9 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
Importer.Import(*From);
}
-bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) {
- if (To->getDefinition())
+bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
+ bool ForceImport) {
+ if (To->getDefinition() || To->isBeingDefined())
return false;
To->startDefinition();
@@ -1791,7 +1841,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) {
if (CXXRecordDecl *ToCXX = dyn_cast<CXXRecordDecl>(To)) {
CXXRecordDecl *FromCXX = cast<CXXRecordDecl>(From);
- llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
+ SmallVector<CXXBaseSpecifier *, 4> Bases;
for (CXXRecordDecl::base_class_iterator
Base1 = FromCXX->bases_begin(),
FromBaseEnd = FromCXX->bases_end();
@@ -1804,7 +1854,10 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) {
SourceLocation EllipsisLoc;
if (Base1->isPackExpansion())
EllipsisLoc = Importer.Import(Base1->getEllipsisLoc());
-
+
+ // Ensure that we have a definition for the base.
+ ImportDefinitionIfNeeded(Base1->getType()->getAsCXXRecordDecl());
+
Bases.push_back(
new (Importer.getToContext())
CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()),
@@ -1818,14 +1871,39 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) {
ToCXX->setBases(Bases.data(), Bases.size());
}
- ImportDeclContext(From);
+ ImportDeclContext(From, ForceImport);
To->completeDefinition();
return false;
}
+bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
+ bool ForceImport) {
+ if (To->getDefinition() || To->isBeingDefined())
+ return false;
+
+ To->startDefinition();
+
+ QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(From));
+ if (T.isNull())
+ return true;
+
+ QualType ToPromotionType = Importer.Import(From->getPromotionType());
+ if (ToPromotionType.isNull())
+ return true;
+
+ ImportDeclContext(From, ForceImport);
+
+ // FIXME: we might need to merge the number of positive or negative bits
+ // if the enumerator lists don't match.
+ To->completeDefinition(T, ToPromotionType,
+ From->getNumPositiveBits(),
+ From->getNumNegativeBits());
+ return false;
+}
+
TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
TemplateParameterList *Params) {
- llvm::SmallVector<NamedDecl *, 4> ToParams;
+ SmallVector<NamedDecl *, 4> ToParams;
ToParams.reserve(Params->size());
for (TemplateParameterList::iterator P = Params->begin(),
PEnd = Params->end();
@@ -1892,7 +1970,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
return TemplateArgument();
case TemplateArgument::Pack: {
- llvm::SmallVector<TemplateArgument, 2> ToPack;
+ SmallVector<TemplateArgument, 2> ToPack;
ToPack.reserve(From.pack_size());
if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack))
return TemplateArgument();
@@ -1910,7 +1988,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
- llvm::SmallVectorImpl<TemplateArgument> &ToArgs) {
+ SmallVectorImpl<TemplateArgument> &ToArgs) {
for (unsigned I = 0; I != NumFromArgs; ++I) {
TemplateArgument To = ImportTemplateArgument(FromArgs[I]);
if (To.isNull() && !FromArgs[I].isNull())
@@ -1969,20 +2047,20 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
else
MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace();
} else {
- llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Namespace))
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace))
continue;
- if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(*Lookup.first)) {
+ if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(FoundDecls[I])) {
MergeWithNamespace = FoundNS;
ConflictingDecls.clear();
break;
}
- ConflictingDecls.push_back(*Lookup.first);
+ ConflictingDecls.push_back(FoundDecls[I]);
}
if (!ConflictingDecls.empty()) {
@@ -2029,21 +2107,21 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
// seen a typedef with the same name (that we can merge with) or any
// other entity by that name (which name lookup could conflict with).
if (!DC->isFunctionOrMethod()) {
- llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
if (TypedefNameDecl *FoundTypedef =
- dyn_cast<TypedefNameDecl>(*Lookup.first)) {
+ dyn_cast<TypedefNameDecl>(FoundDecls[I])) {
if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(),
FoundTypedef->getUnderlyingType()))
return Importer.Imported(D, FoundTypedef);
}
- ConflictingDecls.push_back(*Lookup.first);
+ ConflictingDecls.push_back(FoundDecls[I]);
}
if (!ConflictingDecls.empty()) {
@@ -2065,15 +2143,16 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
SourceLocation StartL = Importer.Import(D->getLocStart());
TypedefNameDecl *ToTypedef;
if (IsAlias)
+ ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC,
+ StartL, Loc,
+ Name.getAsIdentifierInfo(),
+ TInfo);
+ else
ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC,
StartL, Loc,
Name.getAsIdentifierInfo(),
TInfo);
- else
- ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC,
- StartL, Loc,
- Name.getAsIdentifierInfo(),
- TInfo);
+
ToTypedef->setAccess(D->getAccess());
ToTypedef->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToTypedef);
@@ -2109,14 +2188,14 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
// We may already have an enum of the same name; try to find and match it.
if (!DC->isFunctionOrMethod() && SearchName) {
- llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(SearchName, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
- Decl *Found = *Lookup.first;
+ Decl *Found = FoundDecls[I];
if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
Found = Tag->getDecl();
@@ -2127,7 +2206,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
return Importer.Imported(D, FoundEnum);
}
- ConflictingDecls.push_back(*Lookup.first);
+ ConflictingDecls.push_back(FoundDecls[I]);
}
if (!ConflictingDecls.empty()) {
@@ -2157,25 +2236,9 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
D2->setIntegerType(ToIntegerType);
// Import the definition
- if (D->isDefinition()) {
- QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(D));
- if (T.isNull())
- return 0;
+ if (D->isCompleteDefinition() && ImportDefinition(D, D2))
+ return 0;
- QualType ToPromotionType = Importer.Import(D->getPromotionType());
- if (ToPromotionType.isNull())
- return 0;
-
- D2->startDefinition();
- ImportDeclContext(D);
-
- // FIXME: we might need to merge the number of positive or negative bits
- // if the enumerator lists don't match.
- D2->completeDefinition(T, ToPromotionType,
- D->getNumPositiveBits(),
- D->getNumNegativeBits());
- }
-
return D2;
}
@@ -2211,14 +2274,14 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
// We may already have a record of the same name; try to find and match it.
RecordDecl *AdoptDecl = 0;
if (!DC->isFunctionOrMethod() && SearchName) {
- llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(SearchName, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
- Decl *Found = *Lookup.first;
+ Decl *Found = FoundDecls[I];
if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
Found = Tag->getDecl();
@@ -2226,7 +2289,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
- if (!D->isDefinition() || IsStructuralMatch(D, FoundDef)) {
+ if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) {
// The record types structurally match, or the "from" translation
// unit only had a forward declaration anyway; call it the same
// function.
@@ -2241,7 +2304,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
}
}
- ConflictingDecls.push_back(*Lookup.first);
+ ConflictingDecls.push_back(FoundDecls[I]);
}
if (!ConflictingDecls.empty()) {
@@ -2274,7 +2337,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Importer.Imported(D, D2);
- if (D->isDefinition() && ImportDefinition(D, D2))
+ if (D->isCompleteDefinition() && ImportDefinition(D, D2))
return 0;
return D2;
@@ -2295,15 +2358,15 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
// Determine whether there are any other declarations with the same name and
// in the same context.
if (!LexicalDC->isFunctionOrMethod()) {
- llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
- ConflictingDecls.push_back(*Lookup.first);
+ ConflictingDecls.push_back(FoundDecls[I]);
}
if (!ConflictingDecls.empty()) {
@@ -2341,15 +2404,15 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Try to find a function in our own ("to") context with the same name, same
// type, and in the same context as the function we're importing.
if (!LexicalDC->isFunctionOrMethod()) {
- llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
- if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(*Lookup.first)) {
+ if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) {
if (isExternalLinkage(FoundFunction->getLinkage()) &&
isExternalLinkage(D->getLinkage())) {
if (Importer.IsStructurallyEquivalent(D->getType(),
@@ -2374,7 +2437,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
}
- ConflictingDecls.push_back(*Lookup.first);
+ ConflictingDecls.push_back(FoundDecls[I]);
}
if (!ConflictingDecls.empty()) {
@@ -2396,7 +2459,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
return 0;
// Import the function parameters.
- llvm::SmallVector<ParmVarDecl *, 8> Parameters;
+ SmallVector<ParmVarDecl *, 8> Parameters;
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
P != PEnd; ++P) {
ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(*P));
@@ -2416,7 +2479,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
NameInfo, T, TInfo,
FromConstructor->isExplicit(),
D->isInlineSpecified(),
- D->isImplicit());
+ D->isImplicit(),
+ D->isConstexpr());
} else if (isa<CXXDestructorDecl>(D)) {
ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
@@ -2432,6 +2496,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
NameInfo, T, TInfo,
D->isInlineSpecified(),
FromConversion->isExplicit(),
+ D->isConstexpr(),
Importer.Import(D->getLocEnd()));
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
ToFunction = CXXMethodDecl::Create(Importer.getToContext(),
@@ -2441,6 +2506,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
Method->isStatic(),
Method->getStorageClassAsWritten(),
Method->isInlineSpecified(),
+ D->isConstexpr(),
Importer.Import(D->getLocEnd()));
} else {
ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
@@ -2448,7 +2514,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
NameInfo, T, TInfo, D->getStorageClass(),
D->getStorageClassAsWritten(),
D->isInlineSpecified(),
- D->hasWrittenPrototype());
+ D->hasWrittenPrototype(),
+ D->isConstexpr());
}
// Import the qualifier, if any.
@@ -2465,7 +2532,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
Parameters[I]->setOwningFunction(ToFunction);
ToFunction->addDecl(Parameters[I]);
}
- ToFunction->setParams(Parameters.data(), Parameters.size());
+ ToFunction->setParams(Parameters);
// FIXME: Other bits to merge?
@@ -2499,6 +2566,25 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
return 0;
+ // Determine whether we've already imported this field.
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) {
+ if (Importer.IsStructurallyEquivalent(D->getType(),
+ FoundField->getType())) {
+ Importer.Imported(D, FoundField);
+ return FoundField;
+ }
+
+ Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent)
+ << Name << D->getType() << FoundField->getType();
+ Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
+ << FoundField->getType();
+ return 0;
+ }
+ }
+
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
@@ -2531,6 +2617,26 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
return 0;
+ // Determine whether we've already imported this field.
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (IndirectFieldDecl *FoundField
+ = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
+ if (Importer.IsStructurallyEquivalent(D->getType(),
+ FoundField->getType())) {
+ Importer.Imported(D, FoundField);
+ return FoundField;
+ }
+
+ Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent)
+ << Name << D->getType() << FoundField->getType();
+ Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
+ << FoundField->getType();
+ return 0;
+ }
+ }
+
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
@@ -2568,10 +2674,10 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
return 0;
// Determine whether we've already imported this ivar
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(*Lookup.first)) {
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundIvar->getType())) {
Importer.Imported(D, FoundIvar);
@@ -2621,15 +2727,15 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
// in the same context as the variable we're importing.
if (D->isFileVarDecl()) {
VarDecl *MergeWithVar = 0;
- llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
- if (VarDecl *FoundVar = dyn_cast<VarDecl>(*Lookup.first)) {
+ if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) {
// We have found a variable that we may need to merge with. Check it.
if (isExternalLinkage(FoundVar->getLinkage()) &&
isExternalLinkage(D->getLinkage())) {
@@ -2668,7 +2774,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
}
}
- ConflictingDecls.push_back(*Lookup.first);
+ ConflictingDecls.push_back(FoundDecls[I]);
}
if (MergeWithVar) {
@@ -2794,10 +2900,10 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
return 0;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(*Lookup.first)) {
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecls[I])) {
if (FoundMethod->isInstanceMethod() != D->isInstanceMethod())
continue;
@@ -2872,6 +2978,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
D->isInstanceMethod(),
D->isVariadic(),
D->isSynthesized(),
+ D->isImplicit(),
D->isDefined(),
D->getImplementationControl(),
D->hasRelatedResultType());
@@ -2880,7 +2987,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
// deal with implicit parameters.
// Import the parameters
- llvm::SmallVector<ParmVarDecl *, 5> ToParams;
+ SmallVector<ParmVarDecl *, 5> ToParams;
for (ObjCMethodDecl::param_iterator FromP = D->param_begin(),
FromPEnd = D->param_end();
FromP != FromPEnd;
@@ -2897,9 +3004,9 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
ToParams[I]->setOwningFunction(ToMethod);
ToMethod->addDecl(ToParams[I]);
}
- ToMethod->setMethodParams(Importer.getToContext(),
- ToParams.data(), ToParams.size(),
- ToParams.size());
+ SmallVector<SourceLocation, 12> SelLocs;
+ D->getSelectorLocs(SelLocs);
+ ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs);
ToMethod->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToMethod);
@@ -2926,21 +3033,18 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
ObjCCategoryDecl *ToCategory = MergeWithCategory;
if (!ToCategory) {
ToCategory = ObjCCategoryDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getAtLoc()),
+ Importer.Import(D->getAtStartLoc()),
Loc,
Importer.Import(D->getCategoryNameLoc()),
- Name.getAsIdentifierInfo());
+ Name.getAsIdentifierInfo(),
+ ToInterface);
ToCategory->setLexicalDeclContext(LexicalDC);
LexicalDC->addDecl(ToCategory);
Importer.Imported(D, ToCategory);
- // Link this category into its class's category list.
- ToCategory->setClassInterface(ToInterface);
- ToCategory->insertNextClassCategory();
-
// Import protocols
- llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
- llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
+ SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ SmallVector<SourceLocation, 4> ProtocolLocs;
ObjCCategoryDecl::protocol_loc_iterator FromProtoLoc
= D->protocol_loc_begin();
for (ObjCCategoryDecl::protocol_iterator FromProto = D->protocol_begin(),
@@ -2989,21 +3093,22 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
return 0;
ObjCProtocolDecl *MergeWithProtocol = 0;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
continue;
- if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(*Lookup.first)))
+ if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecls[I])))
break;
}
ObjCProtocolDecl *ToProto = MergeWithProtocol;
if (!ToProto || ToProto->isForwardDecl()) {
if (!ToProto) {
- ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, Loc,
- Name.getAsIdentifierInfo());
+ ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC,
+ Name.getAsIdentifierInfo(), Loc,
+ Importer.Import(D->getAtStartLoc()));
ToProto->setForwardDecl(D->isForwardDecl());
ToProto->setLexicalDeclContext(LexicalDC);
LexicalDC->addDecl(ToProto);
@@ -3011,8 +3116,8 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
Importer.Imported(D, ToProto);
// Import protocols
- llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
- llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
+ SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ SmallVector<SourceLocation, 4> ProtocolLocs;
ObjCProtocolDecl::protocol_loc_iterator
FromProtoLoc = D->protocol_loc_begin();
for (ObjCProtocolDecl::protocol_iterator FromProto = D->protocol_begin(),
@@ -3049,23 +3154,22 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
return 0;
ObjCInterfaceDecl *MergeWithIface = 0;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
- if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(*Lookup.first)))
+ if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecls[I])))
break;
}
ObjCInterfaceDecl *ToIface = MergeWithIface;
if (!ToIface || ToIface->isForwardDecl()) {
if (!ToIface) {
- ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(),
- DC, Loc,
- Name.getAsIdentifierInfo(),
- Importer.Import(D->getClassLoc()),
+ ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
+ Importer.Import(D->getAtStartLoc()),
+ Name.getAsIdentifierInfo(), Loc,
D->isForwardDecl(),
D->isImplicitInterfaceDecl());
ToIface->setForwardDecl(D->isForwardDecl());
@@ -3085,8 +3189,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
}
// Import protocols
- llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
- llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
+ SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ SmallVector<SourceLocation, 4> ProtocolLocs;
ObjCInterfaceDecl::protocol_loc_iterator
FromProtoLoc = D->protocol_loc_begin();
@@ -3175,9 +3279,10 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
return 0;
ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getLocation()),
Importer.Import(D->getIdentifier()),
- Category->getClassInterface());
+ Category->getClassInterface(),
+ Importer.Import(D->getLocation()),
+ Importer.Import(D->getAtStartLoc()));
DeclContext *LexicalDC = DC;
if (D->getDeclContext() != D->getLexicalDeclContext()) {
@@ -3219,8 +3324,9 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
// now.
Impl = ObjCImplementationDecl::Create(Importer.getToContext(),
Importer.ImportContext(D->getDeclContext()),
+ Iface, Super,
Importer.Import(D->getLocation()),
- Iface, Super);
+ Importer.Import(D->getAtStartLoc()));
if (D->getDeclContext() != D->getLexicalDeclContext()) {
DeclContext *LexicalDC
@@ -3279,11 +3385,11 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
return 0;
// Check whether we have already imported this property.
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (ObjCPropertyDecl *FoundProp
- = dyn_cast<ObjCPropertyDecl>(*Lookup.first)) {
+ = dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) {
// Check property types.
if (!Importer.IsStructurallyEquivalent(D->getType(),
FoundProp->getType())) {
@@ -3430,8 +3536,8 @@ ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
- llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
- llvm::SmallVector<SourceLocation, 4> Locations;
+ SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ SmallVector<SourceLocation, 4> Locations;
ObjCForwardProtocolDecl::protocol_loc_iterator FromProtoLoc
= D->protocol_loc_begin();
for (ObjCForwardProtocolDecl::protocol_iterator FromProto
@@ -3472,25 +3578,14 @@ Decl *ASTNodeImporter::VisitObjCClassDecl(ObjCClassDecl *D) {
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
-
- llvm::SmallVector<ObjCInterfaceDecl *, 4> Interfaces;
- llvm::SmallVector<SourceLocation, 4> Locations;
- for (ObjCClassDecl::iterator From = D->begin(), FromEnd = D->end();
- From != FromEnd; ++From) {
- ObjCInterfaceDecl *ToIface
- = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface()));
- if (!ToIface)
- continue;
-
- Interfaces.push_back(ToIface);
- Locations.push_back(Importer.Import(From->getLocation()));
- }
-
+ ObjCClassDecl::ObjCClassRef *From = D->getForwardDecl();
+ ObjCInterfaceDecl *ToIface
+ = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface()));
ObjCClassDecl *ToClass = ObjCClassDecl::Create(Importer.getToContext(), DC,
- Loc,
- Interfaces.data(),
- Locations.data(),
- Interfaces.size());
+ Loc,
+ ToIface,
+ Importer.Import(From->getLocation()));
+
ToClass->setLexicalDeclContext(LexicalDC);
LexicalDC->addDecl(ToClass);
Importer.Imported(D, ToClass);
@@ -3594,14 +3689,14 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// We may already have a template of the same name; try to find and match it.
if (!DC->isFunctionOrMethod()) {
- llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
- for (DeclContext::lookup_result Lookup = DC->lookup(Name);
- Lookup.first != Lookup.second;
- ++Lookup.first) {
- if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ SmallVector<NamedDecl *, 4> ConflictingDecls;
+ llvm::SmallVector<NamedDecl *, 2> FoundDecls;
+ DC->localUncachedLookup(Name, FoundDecls);
+ for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
+ if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
- Decl *Found = *Lookup.first;
+ Decl *Found = FoundDecls[I];
if (ClassTemplateDecl *FoundTemplate
= dyn_cast<ClassTemplateDecl>(Found)) {
if (IsStructuralMatch(D, FoundTemplate)) {
@@ -3614,7 +3709,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
}
}
- ConflictingDecls.push_back(*Lookup.first);
+ ConflictingDecls.push_back(FoundDecls[I]);
}
if (!ConflictingDecls.empty()) {
@@ -3660,7 +3755,8 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Importer.Imported(D, D2);
Importer.Imported(DTemplated, D2Templated);
- if (DTemplated->isDefinition() && !D2Templated->isDefinition()) {
+ if (DTemplated->isCompleteDefinition() &&
+ !D2Templated->isCompleteDefinition()) {
// FIXME: Import definition!
}
@@ -3704,7 +3800,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
SourceLocation IdLoc = Importer.Import(D->getLocation());
// Import template arguments.
- llvm::SmallVector<TemplateArgument, 2> TemplateArgs;
+ SmallVector<TemplateArgument, 2> TemplateArgs;
if (ImportTemplateArguments(D->getTemplateArgs().data(),
D->getTemplateArgs().size(),
TemplateArgs))
@@ -3722,7 +3818,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
// FIXME: Check for specialization vs. instantiation errors.
if (RecordDecl *FoundDef = D2->getDefinition()) {
- if (!D->isDefinition() || IsStructuralMatch(D, FoundDef)) {
+ if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) {
// The record types structurally match, or the "from" translation
// unit only had a forward declaration anyway; call it the same
// function.
@@ -3752,7 +3848,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
}
Importer.Imported(D, D2);
- if (D->isDefinition() && ImportDefinition(D, D2))
+ if (D->isCompleteDefinition() && ImportDefinition(D, D2))
return 0;
return D2;
@@ -3792,14 +3888,17 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return 0;
-
- return DeclRefExpr::Create(Importer.getToContext(),
- Importer.Import(E->getQualifierLoc()),
- ToD,
- Importer.Import(E->getLocation()),
- T, E->getValueKind(),
- FoundD,
- /*FIXME:TemplateArgs=*/0);
+
+ DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
+ Importer.Import(E->getQualifierLoc()),
+ ToD,
+ Importer.Import(E->getLocation()),
+ T, E->getValueKind(),
+ FoundD,
+ /*FIXME:TemplateArgs=*/0);
+ if (E->hadMultipleCandidates())
+ DRE->setHadMultipleCandidates(true);
+ return DRE;
}
Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
@@ -3817,8 +3916,8 @@ Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
if (T.isNull())
return 0;
- return new (Importer.getToContext()) CharacterLiteral(E->getValue(),
- E->isWide(), T,
+ return new (Importer.getToContext()) CharacterLiteral(E->getValue(),
+ E->getKind(), T,
Importer.Import(E->getLocation()));
}
@@ -4024,13 +4123,17 @@ Decl *ASTImporter::Import(Decl *FromD) {
if (!FromD)
return 0;
+ ASTNodeImporter Importer(*this);
+
// Check whether we've already imported this declaration.
llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
- if (Pos != ImportedDecls.end())
- return Pos->second;
+ if (Pos != ImportedDecls.end()) {
+ Decl *ToD = Pos->second;
+ Importer.ImportDefinitionIfNeeded(FromD, ToD);
+ return ToD;
+ }
// Import the type
- ASTNodeImporter Importer(*this);
Decl *ToD = Importer.Visit(FromD);
if (!ToD)
return 0;
@@ -4045,7 +4148,7 @@ Decl *ASTImporter::Import(Decl *FromD) {
} else if (TypedefNameDecl *FromTypedef = dyn_cast<TypedefNameDecl>(FromD)) {
// When we've finished transforming a typedef, see whether it was the
// typedef for an anonymous tag.
- for (llvm::SmallVector<TagDecl *, 4>::iterator
+ for (SmallVector<TagDecl *, 4>::iterator
FromTag = AnonTagsWithPendingTypedefs.begin(),
FromTagEnd = AnonTagsWithPendingTypedefs.end();
FromTag != FromTagEnd; ++FromTag) {
@@ -4252,7 +4355,7 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
SourceManager &ToSM = ToContext.getSourceManager();
return ToSM.getLocForStartOfFile(Import(Decomposed.first))
- .getFileLocWithOffset(Decomposed.second);
+ .getLocWithOffset(Decomposed.second);
}
SourceRange ASTImporter::Import(SourceRange FromRange) {
@@ -4306,6 +4409,23 @@ void ASTImporter::ImportDefinition(Decl *From) {
if (DeclContext *FromDC = cast<DeclContext>(From)) {
ASTNodeImporter Importer(*this);
+
+ if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(To)) {
+ if (!ToRecord->getDefinition()) {
+ Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord,
+ /*ForceImport=*/true);
+ return;
+ }
+ }
+
+ if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(To)) {
+ if (!ToEnum->getDefinition()) {
+ Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum,
+ /*ForceImport=*/true);
+ return;
+ }
+ }
+
Importer.ImportDeclContext(FromDC, true);
}
}
@@ -4378,7 +4498,7 @@ Selector ASTImporter::Import(Selector FromSel) {
if (FromSel.isNull())
return Selector();
- llvm::SmallVector<IdentifierInfo *, 4> Idents;
+ SmallVector<IdentifierInfo *, 4> Idents;
Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0)));
for (unsigned I = 1, N = FromSel.getNumArgs(); I < N; ++I)
Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(I)));
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 63583a02bfd1..1f0100a580a3 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -1,6 +1,6 @@
set(LLVM_LINK_COMPONENTS support)
-set(LLVM_USED_LIBS clangBasic)
+set(LLVM_USED_LIBS clangBasic clangLex)
add_clang_library(clangAST
APValue.cpp
@@ -35,6 +35,7 @@ add_clang_library(clangAST
ParentMap.cpp
RecordLayout.cpp
RecordLayoutBuilder.cpp
+ SelectorLocationsKind.cpp
Stmt.cpp
StmtDumper.cpp
StmtIterator.cpp
@@ -46,6 +47,8 @@ add_clang_library(clangAST
Type.cpp
TypeLoc.cpp
TypePrinter.cpp
+ VTableBuilder.cpp
+ VTTBuilder.cpp
)
add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 9ffe1f865689..f29bfd13192d 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -119,7 +119,7 @@ bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const {
bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
void *OpaqueData,
bool AllowShortCircuit) const {
- llvm::SmallVector<const CXXRecordDecl*, 8> Queue;
+ SmallVector<const CXXRecordDecl*, 8> Queue;
const CXXRecordDecl *Record = this;
bool AllMatches = true;
@@ -425,7 +425,7 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
void OverridingMethods::add(unsigned OverriddenSubobject,
UniqueVirtualMethod Overriding) {
- llvm::SmallVector<UniqueVirtualMethod, 4> &SubobjectOverrides
+ SmallVector<UniqueVirtualMethod, 4> &SubobjectOverrides
= Overrides[OverriddenSubobject];
if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
Overriding) == SubobjectOverrides.end())
@@ -556,7 +556,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
// overrides.
typedef std::pair<CXXMethodDecl::method_iterator,
CXXMethodDecl::method_iterator> OverriddenMethods;
- llvm::SmallVector<OverriddenMethods, 4> Stack;
+ SmallVector<OverriddenMethods, 4> Stack;
Stack.push_back(std::make_pair(CanonM->begin_overridden_methods(),
CanonM->end_overridden_methods()));
while (!Stack.empty()) {
@@ -623,11 +623,11 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
SOEnd = OM->second.end();
SO != SOEnd;
++SO) {
- llvm::SmallVector<UniqueVirtualMethod, 4> &Overriding = SO->second;
+ SmallVector<UniqueVirtualMethod, 4> &Overriding = SO->second;
if (Overriding.size() < 2)
continue;
- for (llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
+ for (SmallVector<UniqueVirtualMethod, 4>::iterator
Pos = Overriding.begin(), PosEnd = Overriding.end();
Pos != PosEnd;
/* increment in loop */) {
@@ -642,7 +642,7 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
// in a base class subobject that hides the virtual base class
// subobject.
bool Hidden = false;
- for (llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
+ for (SmallVector<UniqueVirtualMethod, 4>::iterator
OP = Overriding.begin(), OPEnd = Overriding.end();
OP != OPEnd && !Hidden;
++OP) {
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 4c323da7eee3..95d52cb0fa1b 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -28,6 +28,8 @@
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -51,7 +53,7 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) {
// If we're on Mac OS X, an 'availability' for Mac OS X attribute
// implies visibility(default).
- if (D->getASTContext().Target.getTriple().isOSDarwin()) {
+ if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) {
for (specific_attr_iterator<AvailabilityAttr>
A = D->specific_attr_begin<AvailabilityAttr>(),
AEnd = D->specific_attr_end<AvailabilityAttr>();
@@ -818,7 +820,7 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
if (Ctx->isFunctionOrMethod())
return getNameAsString();
- typedef llvm::SmallVector<const DeclContext *, 8> ContextsTy;
+ typedef SmallVector<const DeclContext *, 8> ContextsTy;
ContextsTy Contexts;
// Collect contexts.
@@ -845,18 +847,18 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
if (ND->isAnonymousNamespace())
OS << "<anonymous namespace>";
else
- OS << ND;
+ OS << *ND;
} else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) {
if (!RD->getIdentifier())
OS << "<anonymous " << RD->getKindName() << '>';
else
- OS << RD;
+ OS << *RD;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
const FunctionProtoType *FT = 0;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>());
- OS << FD << '(';
+ OS << *FD << '(';
if (FT) {
unsigned NumParams = FD->getNumParams();
for (unsigned i = 0; i < NumParams; ++i) {
@@ -875,13 +877,13 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
}
OS << ')';
} else {
- OS << cast<NamedDecl>(*I);
+ OS << *cast<NamedDecl>(*I);
}
OS << "::";
}
if (getDeclName())
- OS << this;
+ OS << *this;
else
OS << "<anonymous>";
@@ -1003,8 +1005,7 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
}
// Set qualifier info.
getExtInfo()->QualifierLoc = QualifierLoc;
- }
- else {
+ } else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
if (hasExtInfo()) {
if (getExtInfo()->NumTemplParamLists == 0) {
@@ -1120,15 +1121,16 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
switch (SC) {
- case SC_None: break;
- case SC_Auto: return "auto"; break;
- case SC_Extern: return "extern"; break;
- case SC_PrivateExtern: return "__private_extern__"; break;
- case SC_Register: return "register"; break;
- case SC_Static: return "static"; break;
+ case SC_None: break;
+ case SC_Auto: return "auto";
+ case SC_Extern: return "extern";
+ case SC_OpenCLWorkGroupLocal: return "<<work-group-local>>";
+ case SC_PrivateExtern: return "__private_extern__";
+ case SC_Register: return "register";
+ case SC_Static: return "static";
}
- assert(0 && "Invalid storage class");
+ llvm_unreachable("Invalid storage class");
return 0;
}
@@ -1388,6 +1390,16 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
S, SCAsWritten, DefArg);
}
+SourceRange ParmVarDecl::getSourceRange() const {
+ if (!hasInheritedDefaultArg()) {
+ SourceRange ArgRange = getDefaultArgRange();
+ if (ArgRange.isValid())
+ return SourceRange(getOuterLocStart(), ArgRange.getEnd());
+ }
+
+ return DeclaratorDecl::getSourceRange();
+}
+
Expr *ParmVarDecl::getDefaultArg() {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
assert(!hasUninstantiatedDefaultArg() &&
@@ -1429,6 +1441,15 @@ bool ParmVarDecl::isParameterPack() const {
return isa<PackExpansionType>(getType());
}
+void ParmVarDecl::setParameterIndexLarge(unsigned parameterIndex) {
+ getASTContext().setParameterIndex(this, parameterIndex);
+ ParmVarDeclBits.ParameterIndex = ParameterIndexSentinel;
+}
+
+unsigned ParmVarDecl::getParameterIndexLarge() const {
+ return getASTContext().getParameterIndex(this);
+}
+
//===----------------------------------------------------------------------===//
// FunctionDecl Implementation
//===----------------------------------------------------------------------===//
@@ -1678,20 +1699,14 @@ unsigned FunctionDecl::getNumParams() const {
}
void FunctionDecl::setParams(ASTContext &C,
- ParmVarDecl **NewParamInfo, unsigned NumParams) {
+ llvm::ArrayRef<ParmVarDecl *> NewParamInfo) {
assert(ParamInfo == 0 && "Already has param info!");
- assert(NumParams == getNumParams() && "Parameter count mismatch!");
+ assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!");
// Zero params -> null pointer.
- if (NumParams) {
- void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
- ParamInfo = new (Mem) ParmVarDecl*[NumParams];
- memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
-
- // Update source range. The check below allows us to set EndRangeLoc before
- // setting the parameters.
- if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation())
- EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
+ if (!NewParamInfo.empty()) {
+ ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()];
+ std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
}
}
@@ -1762,6 +1777,33 @@ bool FunctionDecl::isInlined() const {
return false;
}
+/// \brief For a function declaration in C or C++, determine whether this
+/// declaration causes the definition to be externally visible.
+///
+/// Determines whether this is the first non-inline redeclaration of an inline
+/// function in a language where "inline" does not normally require an
+/// externally visible definition.
+bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
+ assert(!doesThisDeclarationHaveABody() &&
+ "Must have a declaration without a body.");
+
+ ASTContext &Context = getASTContext();
+
+ // In C99 mode, a function may have an inline definition (causing it to
+ // be deferred) then redeclared later. As a special case, "extern inline"
+ // is not required to produce an external symbol.
+ if (Context.getLangOptions().GNUInline || !Context.getLangOptions().C99 ||
+ Context.getLangOptions().CPlusPlus)
+ return false;
+ if (getLinkage() != ExternalLinkage || isInlineSpecified())
+ return false;
+ const FunctionDecl *Definition = 0;
+ if (hasBody(Definition))
+ return Definition->isInlined() &&
+ Definition->isInlineDefinitionExternallyVisible();
+ return false;
+}
+
/// \brief For an inline function definition in C or C++, determine whether the
/// definition will be externally visible.
///
@@ -1814,7 +1856,12 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
// Only consider file-scope declarations in this test.
if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
continue;
-
+
+ // Only consider explicit declarations; the presence of a builtin for a
+ // libcall shouldn't affect whether a definition is externally visible.
+ if (Redecl->isImplicit())
+ continue;
+
if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
return true; // Not an inline definition
}
@@ -1857,8 +1904,7 @@ FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
<DependentFunctionTemplateSpecializationInfo*>())
return TK_DependentFunctionTemplateSpecialization;
- assert(false && "Did we miss a TemplateOrSpecialization type?");
- return TK_NonTemplate;
+ llvm_unreachable("Did we miss a TemplateOrSpecialization type?");
}
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
@@ -1890,13 +1936,17 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
switch (getTemplateSpecializationKind()) {
case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
case TSK_ExplicitInstantiationDefinition:
return false;
case TSK_ImplicitInstantiation:
return true;
+ // It is possible to instantiate TSK_ExplicitSpecialization kind
+ // if the FunctionDecl has a class scope specialization pattern.
+ case TSK_ExplicitSpecialization:
+ return getClassScopeSpecializationPattern() != 0;
+
case TSK_ExplicitInstantiationDeclaration:
// Handled below.
break;
@@ -1919,6 +1969,10 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
}
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
+ // Handle class scope explicit specialization special case.
+ if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return getClassScopeSpecializationPattern();
+
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
while (Primary->getInstantiatedFromMemberTemplate()) {
// If we have hit a point where the user provided a specialization of
@@ -1944,6 +1998,10 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
return 0;
}
+FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const {
+ return getASTContext().getClassScopeSpecializationPattern(this);
+}
+
const TemplateArgumentList *
FunctionDecl::getTemplateSpecializationArgs() const {
if (FunctionTemplateSpecializationInfo *Info
@@ -1954,7 +2012,7 @@ FunctionDecl::getTemplateSpecializationArgs() const {
return 0;
}
-const TemplateArgumentListInfo *
+const ASTTemplateArgumentListInfo *
FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
@@ -2069,7 +2127,7 @@ FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
MSInfo->getPointOfInstantiation().isInvalid())
MSInfo->setPointOfInstantiation(PointOfInstantiation);
} else
- assert(false && "Function cannot have a template specialization kind");
+ llvm_unreachable("Function cannot have a template specialization kind");
}
SourceLocation FunctionDecl::getPointOfInstantiation() const {
@@ -2134,6 +2192,12 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
return false;
}
+unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
+ assert(isBitField() && "not a bitfield");
+ Expr *BitWidth = InitializerOrBitWidth.getPointer();
+ return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue();
+}
+
unsigned FieldDecl::getFieldIndex() const {
if (CachedFieldIndex) return CachedFieldIndex - 1;
@@ -2165,8 +2229,8 @@ unsigned FieldDecl::getFieldIndex() const {
}
SourceRange FieldDecl::getSourceRange() const {
- if (isBitField())
- return SourceRange(getInnerLocStart(), getBitWidth()->getLocEnd());
+ if (const Expr *E = InitializerOrBitWidth.getPointer())
+ return SourceRange(getInnerLocStart(), E->getLocEnd());
return DeclaratorDecl::getSourceRange();
}
@@ -2218,22 +2282,22 @@ void TagDecl::completeDefinition() {
cast<CXXRecordDecl>(this)->hasDefinition()) &&
"definition completed but not started");
- IsDefinition = true;
+ IsCompleteDefinition = true;
IsBeingDefined = false;
if (ASTMutationListener *L = getASTMutationListener())
L->CompletedTagDefinition(this);
}
-TagDecl* TagDecl::getDefinition() const {
- if (isDefinition())
+TagDecl *TagDecl::getDefinition() const {
+ if (isCompleteDefinition())
return const_cast<TagDecl *>(this);
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this))
return CXXRD->getDefinition();
for (redecl_iterator R = redecls_begin(), REnd = redecls_end();
R != REnd; ++R)
- if (R->isDefinition())
+ if (R->isCompleteDefinition())
return *R;
return 0;
@@ -2246,8 +2310,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
// Set qualifier info.
getExtInfo()->QualifierLoc = QualifierLoc;
- }
- else {
+ } else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
if (hasExtInfo()) {
if (getExtInfo()->NumTemplParamLists == 0) {
@@ -2296,7 +2359,7 @@ void EnumDecl::completeDefinition(QualType NewType,
QualType NewPromotionType,
unsigned NumPositiveBits,
unsigned NumNegativeBits) {
- assert(!isDefinition() && "Cannot redefine enums!");
+ assert(!isCompleteDefinition() && "Cannot redefine enums!");
if (!IntegerType)
IntegerType = NewType.getTypePtr();
PromotionType = NewPromotionType;
@@ -2349,7 +2412,7 @@ RecordDecl::field_iterator RecordDecl::field_begin() const {
/// completeDefinition - Notes that the definition of this type is now
/// complete.
void RecordDecl::completeDefinition() {
- assert(!isDefinition() && "Cannot redefine record!");
+ assert(!isCompleteDefinition() && "Cannot redefine record!");
TagDecl::completeDefinition();
}
@@ -2360,7 +2423,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
// Notify that we have a RecordDecl doing some initialization.
ExternalASTSource::Deserializing TheFields(Source);
- llvm::SmallVector<Decl*, 64> Decls;
+ SmallVector<Decl*, 64> Decls;
LoadedFieldsFromExternalStorage = true;
switch (Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls)) {
case ELR_Success:
@@ -2380,23 +2443,22 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
if (Decls.empty())
return;
- llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls);
+ llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls,
+ /*FieldsAlreadyLoaded=*/false);
}
//===----------------------------------------------------------------------===//
// BlockDecl Implementation
//===----------------------------------------------------------------------===//
-void BlockDecl::setParams(ParmVarDecl **NewParamInfo,
- unsigned NParms) {
+void BlockDecl::setParams(llvm::ArrayRef<ParmVarDecl *> NewParamInfo) {
assert(ParamInfo == 0 && "Already has param info!");
// Zero params -> null pointer.
- if (NParms) {
- NumParams = NParms;
- void *Mem = getASTContext().Allocate(sizeof(ParmVarDecl*)*NumParams);
- ParamInfo = new (Mem) ParmVarDecl*[NumParams];
- memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
+ if (!NewParamInfo.empty()) {
+ NumParams = NewParamInfo.size();
+ ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()];
+ std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
}
}
@@ -2481,10 +2543,12 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
QualType T, TypeSourceInfo *TInfo,
StorageClass SC, StorageClass SCAsWritten,
bool isInlineSpecified,
- bool hasWrittenPrototype) {
+ bool hasWrittenPrototype,
+ bool isConstexprSpecified) {
FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo,
T, TInfo, SC, SCAsWritten,
- isInlineSpecified);
+ isInlineSpecified,
+ isConstexprSpecified);
New->HasWrittenPrototype = hasWrittenPrototype;
return New;
}
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index b2806f092cbd..321e40b43899 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -43,7 +43,7 @@ static bool StatSwitch = false;
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
- default: assert(0 && "Declaration not in DeclNodes.inc!");
+ default: llvm_unreachable("Declaration not in DeclNodes.inc!");
#define DECL(DERIVED, BASE) case DERIVED: return #DERIVED;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
@@ -62,7 +62,7 @@ void Decl::setInvalidDecl(bool Invalid) {
const char *DeclContext::getDeclKindName() const {
switch (DeclKind) {
- default: assert(0 && "Declaration context not in DeclNodes.inc!");
+ default: llvm_unreachable("Declaration context not in DeclNodes.inc!");
#define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
@@ -100,7 +100,7 @@ void Decl::PrintStats() {
void Decl::add(Kind k) {
switch (k) {
- default: assert(0 && "Declaration not in DeclNodes.inc!");
+ default: llvm_unreachable("Declaration not in DeclNodes.inc!");
#define DECL(DERIVED, BASE) case DERIVED: ++n##DERIVED##s; break;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
@@ -133,14 +133,18 @@ bool Decl::isFunctionOrFunctionTemplate() const {
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
}
-bool Decl::isDefinedOutsideFunctionOrMethod() const {
- for (const DeclContext *DC = getDeclContext();
- DC && !DC->isTranslationUnit();
+bool Decl::isTemplateDecl() const {
+ return isa<TemplateDecl>(this);
+}
+
+const DeclContext *Decl::getParentFunctionOrMethod() const {
+ for (const DeclContext *DC = getDeclContext();
+ DC && !DC->isTranslationUnit() && !DC->isNamespace();
DC = DC->getParent())
if (DC->isFunctionOrMethod())
- return false;
+ return DC;
- return true;
+ return 0;
}
@@ -148,7 +152,7 @@ bool Decl::isDefinedOutsideFunctionOrMethod() const {
// PrettyStackTraceDecl Implementation
//===----------------------------------------------------------------------===//
-void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
+void PrettyStackTraceDecl::print(raw_ostream &OS) const {
SourceLocation TheLoc = Loc;
if (TheLoc.isInvalid() && TheDecl)
TheLoc = TheDecl->getLocation();
@@ -265,13 +269,13 @@ bool Decl::isReferenced() const {
static AvailabilityResult CheckAvailability(ASTContext &Context,
const AvailabilityAttr *A,
std::string *Message) {
- llvm::StringRef TargetPlatform = Context.Target.getPlatformName();
- llvm::StringRef PrettyPlatformName
+ StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
+ StringRef PrettyPlatformName
= AvailabilityAttr::getPrettyPlatformName(TargetPlatform);
if (PrettyPlatformName.empty())
PrettyPlatformName = TargetPlatform;
- VersionTuple TargetMinVersion = Context.Target.getPlatformMinVersion();
+ VersionTuple TargetMinVersion = Context.getTargetInfo().getPlatformMinVersion();
if (TargetMinVersion.empty())
return AR_Available;
@@ -493,6 +497,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case UsingDirective:
case ClassTemplateSpecialization:
case ClassTemplatePartialSpecialization:
+ case ClassScopeFunctionSpecialization:
case ObjCImplementation:
case ObjCCategory:
case ObjCCategoryImpl:
@@ -566,8 +571,7 @@ Decl *Decl::castFromDeclContext (const DeclContext *D) {
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;
+ llvm_unreachable("a decl that inherits DeclContext isn't handled");
}
}
@@ -586,8 +590,7 @@ DeclContext *Decl::castToDeclContext(const Decl *D) {
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;
+ llvm_unreachable("a decl that inherits DeclContext isn't handled");
}
}
@@ -627,7 +630,8 @@ void Decl::CheckAccessDeclContext() const {
isa<ParmVarDecl>(this) ||
// FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have
// AS_none as access specifier.
- isa<CXXRecordDecl>(this))
+ isa<CXXRecordDecl>(this) ||
+ isa<ClassScopeFunctionSpecializationDecl>(this))
return;
assert(Access != AS_none &&
@@ -812,11 +816,15 @@ DeclContext *DeclContext::getNextContext() {
}
std::pair<Decl *, Decl *>
-DeclContext::BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls) {
+DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls,
+ bool FieldsAlreadyLoaded) {
// Build up a chain of declarations via the Decl::NextDeclInContext field.
Decl *FirstNewDecl = 0;
Decl *PrevDecl = 0;
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ if (FieldsAlreadyLoaded && isa<FieldDecl>(Decls[I]))
+ continue;
+
Decl *D = Decls[I];
if (PrevDecl)
PrevDecl->NextDeclInContext = D;
@@ -838,9 +846,9 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
// Notify that we have a DeclContext that is initializing.
ExternalASTSource::Deserializing ADeclContext(Source);
-
+
// Load the external declarations, if any.
- llvm::SmallVector<Decl*, 64> Decls;
+ SmallVector<Decl*, 64> Decls;
ExternalLexicalStorage = false;
switch (Source->FindExternalLexicalDecls(this, Decls)) {
case ELR_Success:
@@ -855,17 +863,16 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
return;
// We may have already loaded just the fields of this record, in which case
- // don't add the decls, just replace the FirstDecl/LastDecl chain.
+ // we need to ignore them.
+ bool FieldsAlreadyLoaded = false;
if (const RecordDecl *RD = dyn_cast<RecordDecl>(this))
- if (RD->LoadedFieldsFromExternalStorage) {
- llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls);
- return;
- }
-
+ FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage;
+
// Splice the newly-read declarations into the beginning of the list
// of declarations.
Decl *ExternalFirst, *ExternalLast;
- llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls);
+ llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls,
+ FieldsAlreadyLoaded);
ExternalLast->NextDeclInContext = FirstDecl;
FirstDecl = ExternalFirst;
if (!LastDecl)
@@ -890,7 +897,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclContext::lookup_result
ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
- llvm::SmallVectorImpl<NamedDecl*> &Decls) {
+ ArrayRef<NamedDecl*> Decls) {
ASTContext &Context = DC->getParentASTContext();;
StoredDeclsMap *Map;
@@ -898,35 +905,17 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
Map = DC->CreateStoredDeclsMap(Context);
StoredDeclsList &List = (*Map)[Name];
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ for (ArrayRef<NamedDecl*>::iterator
+ I = Decls.begin(), E = Decls.end(); I != E; ++I) {
if (List.isNull())
- List.setOnlyValue(Decls[I]);
+ List.setOnlyValue(*I);
else
- List.AddSubsequentDecl(Decls[I]);
+ List.AddSubsequentDecl(*I);
}
return List.getLookupResult();
}
-void ExternalASTSource::MaterializeVisibleDeclsForName(const DeclContext *DC,
- DeclarationName Name,
- llvm::SmallVectorImpl<NamedDecl*> &Decls) {
- assert(DC->LookupPtr);
- StoredDeclsMap &Map = *DC->LookupPtr;
-
- // If there's an entry in the table the visible decls for this name have
- // already been deserialized.
- if (Map.find(Name) == Map.end()) {
- StoredDeclsList &List = Map[Name];
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- if (List.isNull())
- List.setOnlyValue(Decls[I]);
- else
- List.AddSubsequentDecl(Decls[I]);
- }
- }
-}
-
DeclContext::decl_iterator DeclContext::noload_decls_begin() const {
return decl_iterator(FirstDecl);
}
@@ -939,8 +928,6 @@ DeclContext::decl_iterator DeclContext::decls_begin() const {
if (hasExternalLexicalStorage())
LoadLexicalDeclsFromExternalStorage();
- // FIXME: Check whether we need to load some declarations from
- // external storage.
return decl_iterator(FirstDecl);
}
@@ -988,6 +975,9 @@ void DeclContext::removeDecl(Decl *D) {
if (isa<NamedDecl>(D)) {
NamedDecl *ND = cast<NamedDecl>(D);
+ // Remove only decls that have a name
+ if (!ND->getDeclName()) return;
+
StoredDeclsMap *Map = getPrimaryContext()->LookupPtr;
if (!Map) return;
@@ -1038,12 +1028,10 @@ void DeclContext::buildLookup(DeclContext *DCtx) {
if (D->getDeclContext() == DCtx)
makeDeclVisibleInContextImpl(ND);
- // Insert any forward-declared Objective-C interfaces into the lookup
+ // Insert any forward-declared Objective-C interface into the lookup
// data structure.
if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D))
- for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
- I != IEnd; ++I)
- makeDeclVisibleInContextImpl(I->getInterface());
+ makeDeclVisibleInContextImpl(Class->getForwardInterfaceDecl());
// If this declaration is itself a transparent declaration context or
// inline namespace, add its members (recursively).
@@ -1093,6 +1081,38 @@ DeclContext::lookup(DeclarationName Name) const {
return const_cast<DeclContext*>(this)->lookup(Name);
}
+void DeclContext::localUncachedLookup(DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl *> &Results) {
+ Results.clear();
+
+ // If there's no external storage, just perform a normal lookup and copy
+ // the results.
+ if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage()) {
+ lookup_result LookupResults = lookup(Name);
+ Results.insert(Results.end(), LookupResults.first, LookupResults.second);
+ return;
+ }
+
+ // If we have a lookup table, check there first. Maybe we'll get lucky.
+ if (LookupPtr) {
+ StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
+ if (Pos != LookupPtr->end()) {
+ Results.insert(Results.end(),
+ Pos->second.getLookupResult().first,
+ Pos->second.getLookupResult().second);
+ return;
+ }
+ }
+
+ // Slow case: grovel through the declarations in our chain looking for
+ // matches.
+ for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (ND->getDeclName() == Name)
+ Results.push_back(ND);
+ }
+}
+
DeclContext *DeclContext::getRedeclContext() {
DeclContext *Ctx = this;
// Skip through transparent contexts.
@@ -1205,15 +1225,6 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
DeclNameEntries.AddSubsequentDecl(D);
}
-void DeclContext::MaterializeVisibleDeclsFromExternalStorage() {
- ExternalASTSource *Source = getParentASTContext().getExternalSource();
- assert(hasExternalVisibleStorage() && Source && "No external storage?");
-
- if (!LookupPtr)
- CreateStoredDeclsMap(getParentASTContext());
- Source->MaterializeVisibleDecls(this);
-}
-
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
/// this context.
DeclContext::udir_iterator_range
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 4b59bf37d74b..f3da67c4ff81 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -35,15 +35,16 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
HasMutableFields(false), HasTrivialDefaultConstructor(true),
- HasConstExprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true),
+ HasConstexprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true),
HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false),
DeclaredCopyConstructor(false), DeclaredMoveConstructor(false),
DeclaredCopyAssignment(false), DeclaredMoveAssignment(false),
- DeclaredDestructor(false), NumBases(0), NumVBases(0), Bases(), VBases(),
- Definition(D), FirstFriend(0) {
+ DeclaredDestructor(false), FailedImplicitMoveConstructor(false),
+ FailedImplicitMoveAssignment(false), NumBases(0), NumVBases(0), Bases(),
+ VBases(), Definition(D), FirstFriend(0) {
}
CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@@ -89,7 +90,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes;
// The virtual bases of this class.
- llvm::SmallVector<const CXXBaseSpecifier *, 8> VBases;
+ SmallVector<const CXXBaseSpecifier *, 8> VBases;
data().Bases = new(C) CXXBaseSpecifier [NumBases];
data().NumBases = NumBases;
@@ -287,7 +288,7 @@ bool CXXRecordDecl::isTriviallyCopyable() const {
/// (if there is one).
static CXXMethodDecl *
GetBestOverloadCandidateSimple(
- const llvm::SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) {
+ const SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) {
if (Cands.empty())
return 0;
if (Cands.size() == 1)
@@ -313,7 +314,7 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(unsigned TypeQuals) const{
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
unsigned FoundTQs;
- llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found;
+ SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found;
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName);
Con != ConEnd; ++Con) {
@@ -349,7 +350,7 @@ CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const {
QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this));
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
- llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found;
+ SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found;
DeclContext::lookup_const_iterator Op, OpEnd;
for (llvm::tie(Op, OpEnd) = this->lookup(Name); Op != OpEnd; ++Op) {
// C++ [class.copy]p9:
@@ -502,18 +503,18 @@ NotASpecialMember:;
// Note that we have a user-declared constructor.
data().UserDeclaredConstructor = true;
- // FIXME: Under C++0x, /only/ special member functions may be user-provided.
- // This is probably a defect.
- bool UserProvided = false;
+ // Technically, "user-provided" is only defined for special member
+ // functions, but the intent of the standard is clearly that it should apply
+ // to all functions.
+ bool UserProvided = Constructor->isUserProvided();
// C++0x [class.ctor]p5:
// A default constructor is trivial if it is not user-provided [...]
if (Constructor->isDefaultConstructor()) {
data().DeclaredDefaultConstructor = true;
- if (Constructor->isUserProvided()) {
+ if (UserProvided) {
data().HasTrivialDefaultConstructor = false;
data().UserProvidedDefaultConstructor = true;
- UserProvided = true;
}
}
@@ -527,10 +528,8 @@ NotASpecialMember:;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if it is not
// user-provided [...]
- if (Constructor->isUserProvided()) {
+ if (UserProvided)
data().HasTrivialCopyConstructor = false;
- UserProvided = true;
- }
} else if (Constructor->isMoveConstructor()) {
data().UserDeclaredMoveConstructor = true;
data().DeclaredMoveConstructor = true;
@@ -538,17 +537,14 @@ NotASpecialMember:;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if it is not
// user-provided [...]
- if (Constructor->isUserProvided()) {
+ if (UserProvided)
data().HasTrivialMoveConstructor = false;
- UserProvided = true;
- }
}
}
- if (Constructor->isConstExpr() &&
- !Constructor->isCopyOrMoveConstructor()) {
- // Record if we see any constexpr constructors which are niether copy
+ if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) {
+ // Record if we see any constexpr constructors which are neither copy
// nor move constructors.
- data().HasConstExprNonCopyMoveConstructor = true;
+ data().HasConstexprNonCopyMoveConstructor = true;
}
// C++ [dcl.init.aggr]p1:
@@ -657,6 +653,13 @@ NotASpecialMember:;
// Handle non-static data members.
if (FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
+ // C++ [class.bit]p2:
+ // A declaration for a bit-field that omits the identifier declares an
+ // unnamed bit-field. Unnamed bit-fields are not members and cannot be
+ // initialized.
+ if (Field->isUnnamedBitfield())
+ return;
+
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with [...] no
// private or protected non-static data members (clause 11).
@@ -675,7 +678,7 @@ NotASpecialMember:;
case AS_private: data().HasPrivateFields = true; break;
case AS_protected: data().HasProtectedFields = true; break;
case AS_public: data().HasPublicFields = true; break;
- case AS_none: assert(0 && "Invalid access specifier");
+ case AS_none: llvm_unreachable("Invalid access specifier");
};
if ((data().HasPrivateFields + data().HasProtectedFields +
data().HasPublicFields) > 1)
@@ -716,7 +719,11 @@ NotASpecialMember:;
}
// Record if this field is the first non-literal field or base.
- if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType())
+ // As a slight variation on the standard, we regard mutable members as being
+ // non-literal, since mutating a constexpr variable would break C++11
+ // constant expression semantics.
+ if ((!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) ||
+ Field->isMutable())
data().HasNonLiteralTypeFieldsOrBases = true;
if (Field->hasInClassInitializer()) {
@@ -827,15 +834,11 @@ NotASpecialMember:;
// If this is not a zero-length bit-field, then the class is not empty.
if (data().Empty) {
- if (!Field->getBitWidth())
+ if (!Field->isBitField() ||
+ (!Field->getBitWidth()->isTypeDependent() &&
+ !Field->getBitWidth()->isValueDependent() &&
+ Field->getBitWidthValue(Context) != 0))
data().Empty = false;
- else if (!Field->getBitWidth()->isTypeDependent() &&
- !Field->getBitWidth()->isValueDependent()) {
- llvm::APSInt Bits;
- if (Field->getBitWidth()->isIntegerConstantExpr(Bits, Context))
- if (!!Bits)
- data().Empty = false;
- }
}
}
@@ -1057,7 +1060,7 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
return;
}
- assert(false && "Not a class template or member class specialization");
+ llvm_unreachable("Not a class template or member class specialization");
}
CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
@@ -1160,9 +1163,10 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isStatic, StorageClass SCAsWritten, bool isInline,
- SourceLocation EndLocation) {
+ bool isConstexpr, SourceLocation EndLocation) {
return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo,
- isStatic, SCAsWritten, isInline, EndLocation);
+ isStatic, SCAsWritten, isInline, isConstexpr,
+ EndLocation);
}
bool CXXMethodDecl::isUsualDeallocationFunction() const {
@@ -1402,7 +1406,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
CXXConstructorDecl *
CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) {
return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationNameInfo(),
- QualType(), 0, false, false, false);
+ QualType(), 0, false, false, false, false);
}
CXXConstructorDecl *
@@ -1410,14 +1414,14 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
- bool isExplicit,
- bool isInline,
- bool isImplicitlyDeclared) {
+ bool isExplicit, bool isInline,
+ bool isImplicitlyDeclared, bool isConstexpr) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
return new (C) CXXConstructorDecl(RD, StartLoc, NameInfo, T, TInfo,
- isExplicit, isInline, isImplicitlyDeclared);
+ isExplicit, isInline, isImplicitlyDeclared,
+ isConstexpr);
}
bool CXXConstructorDecl::isDefaultConstructor() const {
@@ -1545,8 +1549,7 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
- bool isInline,
- bool isImplicitlyDeclared) {
+ bool isInline, bool isImplicitlyDeclared) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXDestructorName &&
"Name must refer to a destructor");
@@ -1557,7 +1560,7 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
CXXConversionDecl *
CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) {
return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(),
- QualType(), 0, false, false,
+ QualType(), 0, false, false, false,
SourceLocation());
}
@@ -1567,12 +1570,13 @@ CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicit,
- SourceLocation EndLocation) {
+ bool isConstexpr, SourceLocation EndLocation) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConversionFunctionName &&
"Name must refer to a conversion function");
return new (C) CXXConversionDecl(RD, StartLoc, NameInfo, T, TInfo,
- isInline, isExplicit, EndLocation);
+ isInline, isExplicit, isConstexpr,
+ EndLocation);
}
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
@@ -1696,8 +1700,7 @@ static const char *getAccessName(AccessSpecifier AS) {
switch (AS) {
default:
case AS_none:
- assert("Invalid access specifier!");
- return 0;
+ llvm_unreachable("Invalid access specifier!");
case AS_public:
return "public";
case AS_private:
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 557b681d2fa6..a589b7f9d3e9 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/ASTMutationListener.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;
@@ -185,7 +186,7 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
// Check for duplicate protocol in class's protocol list.
// This is O(n*m). But it is extremely rare and number of protocols in
// class or its extension are very few.
- llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
+ SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
for (unsigned i = 0; i < ExtNum; i++) {
bool protocolExists = false;
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
@@ -337,17 +338,60 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
bool isInstance,
bool isVariadic,
bool isSynthesized,
+ bool isImplicitlyDeclared,
bool isDefined,
ImplementationControl impControl,
- bool HasRelatedResultType,
- unsigned numSelectorArgs) {
+ bool HasRelatedResultType) {
return new (C) ObjCMethodDecl(beginLoc, endLoc,
SelInfo, T, ResultTInfo, contextDecl,
isInstance,
- isVariadic, isSynthesized, isDefined,
+ isVariadic, isSynthesized, isImplicitlyDeclared,
+ isDefined,
impControl,
- HasRelatedResultType,
- numSelectorArgs);
+ HasRelatedResultType);
+}
+
+void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
+ assert(PrevMethod);
+ getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
+ IsRedeclaration = true;
+ PrevMethod->HasRedeclaration = true;
+}
+
+void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
+ ArrayRef<ParmVarDecl*> Params,
+ ArrayRef<SourceLocation> SelLocs) {
+ ParamsAndSelLocs = 0;
+ NumParams = Params.size();
+ if (Params.empty() && SelLocs.empty())
+ return;
+
+ unsigned Size = sizeof(ParmVarDecl *) * NumParams +
+ sizeof(SourceLocation) * SelLocs.size();
+ ParamsAndSelLocs = C.Allocate(Size);
+ std::copy(Params.begin(), Params.end(), getParams());
+ std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
+}
+
+void ObjCMethodDecl::getSelectorLocs(
+ SmallVectorImpl<SourceLocation> &SelLocs) const {
+ for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
+ SelLocs.push_back(getSelectorLoc(i));
+}
+
+void ObjCMethodDecl::setMethodParams(ASTContext &C,
+ ArrayRef<ParmVarDecl*> Params,
+ ArrayRef<SourceLocation> SelLocs) {
+ assert((!SelLocs.empty() || isImplicit()) &&
+ "No selector locs for non-implicit method");
+ if (isImplicit())
+ return setParamsAndSelLocs(C, Params, ArrayRef<SourceLocation>());
+
+ SelLocsKind = hasStandardSelectorLocs(getSelector(), SelLocs, Params, EndLoc);
+ if (SelLocsKind != SelLoc_NonStandard)
+ return setParamsAndSelLocs(C, Params, ArrayRef<SourceLocation>());
+
+ setParamsAndSelLocs(C, Params, SelLocs);
}
/// \brief A definition will return its interface declaration.
@@ -356,6 +400,11 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
ASTContext &Ctx = getASTContext();
ObjCMethodDecl *Redecl = 0;
+ if (HasRedeclaration)
+ Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this));
+ if (Redecl)
+ return Redecl;
+
Decl *CtxD = cast<Decl>(getDeclContext());
if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
@@ -377,6 +426,12 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
}
+ if (!Redecl && isRedeclaration()) {
+ // This is the last redeclaration, go back to the first method.
+ return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
+ isInstanceMethod());
+ }
+
return Redecl ? Redecl : this;
}
@@ -444,6 +499,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
// These selectors have a conventional meaning only for instance methods.
case OMF_dealloc:
+ case OMF_finalize:
case OMF_retain:
case OMF_release:
case OMF_autorelease:
@@ -545,8 +601,7 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
return IMD->getClassInterface();
assert(!isa<ObjCProtocolDecl>(getDeclContext()) && "It's a protocol method");
- assert(false && "unknown method context");
- return 0;
+ llvm_unreachable("unknown method context");
}
//===----------------------------------------------------------------------===//
@@ -566,11 +621,10 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
ObjCInterfaceDecl::
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal)
- : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
+ : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
TypeForDecl(0), SuperClass(0),
CategoryList(0), IvarList(0),
- ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false),
- ClassLoc(CLoc) {
+ ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false) {
}
void ObjCInterfaceDecl::LoadExternalDefinition() const {
@@ -756,8 +810,7 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
ID = IM->getClassInterface();
if (BW)
IM->setHasSynthBitfield(true);
- }
- else {
+ } else {
ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
ID = CD->getClassInterface();
if (BW)
@@ -778,8 +831,7 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
default:
case ObjCCategoryImpl:
case ObjCProtocol:
- assert(0 && "invalid ivar container!");
- return 0;
+ llvm_unreachable("invalid ivar container!");
// Ivars can only appear in class extension categories.
case ObjCCategory: {
@@ -812,9 +864,10 @@ ObjCAtDefsFieldDecl
//===----------------------------------------------------------------------===//
ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- IdentifierInfo *Id) {
- return new (C) ObjCProtocolDecl(DC, L, Id);
+ IdentifierInfo *Id,
+ SourceLocation nameLoc,
+ SourceLocation atStartLoc) {
+ return new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc);
}
ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
@@ -850,36 +903,31 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
//===----------------------------------------------------------------------===//
ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L,
- ObjCInterfaceDecl *const *Elts,
- const SourceLocation *Locs,
- unsigned nElts,
+ ObjCInterfaceDecl *const Elt,
+ const SourceLocation Loc,
ASTContext &C)
: Decl(ObjCClass, DC, L) {
- setClassList(C, Elts, Locs, nElts);
-}
-
-void ObjCClassDecl::setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
- const SourceLocation *Locs, unsigned Num) {
- ForwardDecls = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef)*Num,
- llvm::alignOf<ObjCClassRef>());
- for (unsigned i = 0; i < Num; ++i)
- new (&ForwardDecls[i]) ObjCClassRef(List[i], Locs[i]);
-
- NumDecls = Num;
+ setClass(C, Elt, Loc);
}
ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
- ObjCInterfaceDecl *const *Elts,
- const SourceLocation *Locs,
- unsigned nElts) {
- return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C);
+ ObjCInterfaceDecl *const Elt,
+ const SourceLocation Loc) {
+ return new (C) ObjCClassDecl(DC, L, Elt, Loc, C);
}
+void ObjCClassDecl::setClass(ASTContext &C, ObjCInterfaceDecl*const Cls,
+ const SourceLocation Loc) {
+
+ ForwardDecl = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef),
+ llvm::alignOf<ObjCClassRef>());
+ new (ForwardDecl) ObjCClassRef(Cls, Loc);
+}
+
SourceRange ObjCClassDecl::getSourceRange() const {
// FIXME: We should include the semicolon
- assert(NumDecls);
- return SourceRange(getLocation(), ForwardDecls[NumDecls-1].getLocation());
+ return SourceRange(getLocation(), ForwardDecl->getLocation());
}
//===----------------------------------------------------------------------===//
@@ -912,8 +960,25 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
- IdentifierInfo *Id) {
- return new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id);
+ IdentifierInfo *Id,
+ ObjCInterfaceDecl *IDecl) {
+ ObjCCategoryDecl *CatDecl = new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc,
+ CategoryNameLoc, Id,
+ IDecl);
+ if (IDecl) {
+ // Link this category into its class's category list.
+ CatDecl->NextClassCategory = IDecl->getCategoryList();
+ IDecl->setCategoryList(CatDecl);
+ if (ASTMutationListener *L = C.getASTMutationListener())
+ L->AddedObjCCategoryToInterface(CatDecl, IDecl);
+ }
+
+ return CatDecl;
+}
+
+ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(),
+ SourceLocation(), 0, 0);
}
ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
@@ -932,9 +997,12 @@ void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
ObjCCategoryImplDecl *
ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,IdentifierInfo *Id,
- ObjCInterfaceDecl *ClassInterface) {
- return new (C) ObjCCategoryImplDecl(DC, L, Id, ClassInterface);
+ IdentifierInfo *Id,
+ ObjCInterfaceDecl *ClassInterface,
+ SourceLocation nameLoc,
+ SourceLocation atStartLoc) {
+ return new (C) ObjCCategoryImplDecl(DC, Id, ClassInterface,
+ nameLoc, atStartLoc);
}
ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
@@ -997,7 +1065,7 @@ FindPropertyImplDecl(IdentifierInfo *Id) const {
return 0;
}
-llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
+raw_ostream &clang::operator<<(raw_ostream &OS,
const ObjCCategoryImplDecl *CID) {
OS << CID->getName();
return OS;
@@ -1009,13 +1077,28 @@ llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
ObjCImplementationDecl *
ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
ObjCInterfaceDecl *ClassInterface,
- ObjCInterfaceDecl *SuperDecl) {
- return new (C) ObjCImplementationDecl(DC, L, ClassInterface, SuperDecl);
+ ObjCInterfaceDecl *SuperDecl,
+ SourceLocation nameLoc,
+ SourceLocation atStartLoc) {
+ return new (C) ObjCImplementationDecl(DC, ClassInterface, SuperDecl,
+ nameLoc, atStartLoc);
+}
+
+void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
+ CXXCtorInitializer ** initializers,
+ unsigned numInitializers) {
+ if (numInitializers > 0) {
+ NumIvarInitializers = numInitializers;
+ CXXCtorInitializer **ivarInitializers =
+ new (C) CXXCtorInitializer*[NumIvarInitializers];
+ memcpy(ivarInitializers, initializers,
+ numInitializers * sizeof(CXXCtorInitializer*));
+ IvarInitializers = ivarInitializers;
+ }
}
-llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
+raw_ostream &clang::operator<<(raw_ostream &OS,
const ObjCImplementationDecl *ID) {
OS << ID->getName();
return OS;
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 19554a3baaea..08a1ab5723cd 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -24,22 +24,25 @@ using namespace clang;
namespace {
class DeclPrinter : public DeclVisitor<DeclPrinter> {
- llvm::raw_ostream &Out;
+ raw_ostream &Out;
ASTContext &Context;
PrintingPolicy Policy;
unsigned Indentation;
+ bool PrintInstantiation;
- llvm::raw_ostream& Indent() { return Indent(Indentation); }
- llvm::raw_ostream& Indent(unsigned Indentation);
- void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls);
+ raw_ostream& Indent() { return Indent(Indentation); }
+ raw_ostream& Indent(unsigned Indentation);
+ void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
void Print(AccessSpecifier AS);
public:
- DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context,
+ DeclPrinter(raw_ostream &Out, ASTContext &Context,
const PrintingPolicy &Policy,
- unsigned Indentation = 0)
- : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { }
+ unsigned Indentation = 0,
+ bool PrintInstantiation = false)
+ : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation),
+ PrintInstantiation(PrintInstantiation) { }
void VisitDeclContext(DeclContext *DC, bool Indent = true);
@@ -62,6 +65,8 @@ namespace {
void VisitCXXRecordDecl(CXXRecordDecl *D);
void VisitLinkageSpecDecl(LinkageSpecDecl *D);
void VisitTemplateDecl(const TemplateDecl *D);
+ void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitObjCMethodDecl(ObjCMethodDecl *D);
void VisitObjCClassDecl(ObjCClassDecl *D);
void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
@@ -77,16 +82,20 @@ namespace {
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
void VisitUsingDecl(UsingDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
+
+ void PrintTemplateParameters(const TemplateParameterList *Params,
+ const TemplateArgumentList *Args);
};
}
-void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const {
- print(Out, getASTContext().PrintingPolicy, Indentation);
+void Decl::print(raw_ostream &Out, unsigned Indentation,
+ bool PrintInstantiation) const {
+ print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);
}
-void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
- unsigned Indentation) const {
- DeclPrinter Printer(Out, getASTContext(), Policy, Indentation);
+void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
+ unsigned Indentation, bool PrintInstantiation) const {
+ DeclPrinter Printer(Out, getASTContext(), Policy, Indentation, PrintInstantiation);
Printer.Visit(const_cast<Decl*>(this));
}
@@ -105,7 +114,7 @@ static QualType GetBaseType(QualType T) {
else if (const VectorType *VTy = BaseType->getAs<VectorType>())
BaseType = VTy->getElementType();
else
- assert(0 && "Unknown declarator!");
+ llvm_unreachable("Unknown declarator!");
}
return BaseType;
}
@@ -119,7 +128,7 @@ static QualType getDeclType(Decl* D) {
}
void Decl::printGroup(Decl** Begin, unsigned NumDecls,
- llvm::raw_ostream &Out, const PrintingPolicy &Policy,
+ raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation) {
if (NumDecls == 1) {
(*Begin)->print(Out, Policy, Indentation);
@@ -132,7 +141,7 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls,
++Begin;
PrintingPolicy SubPolicy(Policy);
- if (TD && TD->isDefinition()) {
+ if (TD && TD->isCompleteDefinition()) {
TD->print(Out, Policy, Indentation);
Out << " ";
SubPolicy.SuppressTag = true;
@@ -159,7 +168,7 @@ void DeclContext::dumpDeclContext() const {
DC = DC->getParent();
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
- DeclPrinter Printer(llvm::errs(), Ctx, Ctx.PrintingPolicy, 0);
+ DeclPrinter Printer(llvm::errs(), Ctx, Ctx.getPrintingPolicy(), 0);
Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
}
@@ -167,13 +176,13 @@ void Decl::dump() const {
print(llvm::errs());
}
-llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
+raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
for (unsigned i = 0; i != Indentation; ++i)
Out << " ";
return Out;
}
-void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) {
+void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
this->Indent();
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
Out << ";\n";
@@ -183,7 +192,7 @@ void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) {
void DeclPrinter::Print(AccessSpecifier AS) {
switch(AS) {
- case AS_none: assert(0 && "No access specifier!"); break;
+ case AS_none: llvm_unreachable("No access specifier!");
case AS_public: Out << "public"; break;
case AS_protected: Out << "protected"; break;
case AS_private: Out << "private"; break;
@@ -198,7 +207,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (Indent)
Indentation += Policy.Indentation;
- llvm::SmallVector<Decl*, 2> Decls;
+ SmallVector<Decl*, 2> Decls;
for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
D != DEnd; ++D) {
@@ -304,8 +313,12 @@ void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
std::string S = D->getNameAsString();
D->getUnderlyingType().getAsStringInternal(S, Policy);
- if (!Policy.SuppressSpecifiers)
+ if (!Policy.SuppressSpecifiers) {
Out << "typedef ";
+
+ if (D->isModulePrivate())
+ Out << "__module_private__ ";
+ }
Out << S;
}
@@ -315,6 +328,8 @@ void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
}
void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
+ if (!Policy.SuppressSpecifiers && D->isModulePrivate())
+ Out << "__module_private__ ";
Out << "enum ";
if (D->isScoped()) {
if (D->isScopedUsingClassTag())
@@ -322,7 +337,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
else
Out << "struct ";
}
- Out << D;
+ Out << *D;
if (D->isFixed()) {
std::string Underlying;
@@ -330,7 +345,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
Out << " : " << Underlying;
}
- if (D->isDefinition()) {
+ if (D->isCompleteDefinition()) {
Out << " {\n";
VisitDeclContext(D);
Indent() << "}";
@@ -338,11 +353,13 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
}
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
+ if (!Policy.SuppressSpecifiers && D->isModulePrivate())
+ Out << "__module_private__ ";
Out << D->getKindName();
if (D->getIdentifier())
- Out << ' ' << D;
+ Out << ' ' << *D;
- if (D->isDefinition()) {
+ if (D->isCompleteDefinition()) {
Out << " {\n";
VisitDeclContext(D);
Indent() << "}";
@@ -350,7 +367,7 @@ void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
}
void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
- Out << D;
+ Out << *D;
if (Expr *Init = D->getInitExpr()) {
Out << " = ";
Init->printPretty(Out, Context, 0, Policy, Indentation);
@@ -364,11 +381,13 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
case SC_Extern: Out << "extern "; break;
case SC_Static: Out << "static "; break;
case SC_PrivateExtern: Out << "__private_extern__ "; break;
- case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions");
+ case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal:
+ llvm_unreachable("invalid for functions");
}
- if (D->isInlineSpecified()) Out << "inline ";
+ if (D->isInlineSpecified()) Out << "inline ";
if (D->isVirtualAsWritten()) Out << "virtual ";
+ if (D->isModulePrivate()) Out << "__module_private__ ";
}
PrintingPolicy SubPolicy(Policy);
@@ -449,6 +468,10 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (D->hasAttr<NoReturnAttr>())
Proto += " __attribute((noreturn))";
+
+ if (D->hasAttr<ReturnsTwiceAttr>())
+ Proto += " __attribute((returns_twice))";
+
if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
bool HasInitializerList = false;
for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
@@ -468,10 +491,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (BMInitializer->isAnyMemberInitializer()) {
FieldDecl *FD = BMInitializer->getAnyMember();
- Out << FD;
+ Out << *FD;
} else {
- Out << QualType(BMInitializer->getBaseClass(),
- 0).getAsString(Policy);
+ Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
}
Out << "(";
@@ -549,6 +571,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
if (!Policy.SuppressSpecifiers && D->isMutable())
Out << "mutable ";
+ if (!Policy.SuppressSpecifiers && D->isModulePrivate())
+ Out << "__module_private__ ";
std::string Name = D->getNameAsString();
D->getType().getAsStringInternal(Name, Policy);
@@ -577,6 +601,8 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
Out << "__thread ";
+ if (!Policy.SuppressSpecifiers && D->isModulePrivate())
+ Out << "__module_private__ ";
std::string Name = D->getNameAsString();
QualType T = D->getType();
@@ -621,7 +647,7 @@ void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
// C++ declarations
//----------------------------------------------------------------------------
void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
- Out << "namespace " << D << " {\n";
+ Out << "namespace " << *D << " {\n";
VisitDeclContext(D);
Indent() << "}";
}
@@ -630,22 +656,24 @@ void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
Out << "using namespace ";
if (D->getQualifier())
D->getQualifier()->print(Out, Policy);
- Out << D->getNominatedNamespaceAsWritten();
+ Out << *D->getNominatedNamespaceAsWritten();
}
void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
- Out << "namespace " << D << " = ";
+ Out << "namespace " << *D << " = ";
if (D->getQualifier())
D->getQualifier()->print(Out, Policy);
- Out << D->getAliasedNamespace();
+ Out << *D->getAliasedNamespace();
}
void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ if (!Policy.SuppressSpecifiers && D->isModulePrivate())
+ Out << "__module_private__ ";
Out << D->getKindName();
if (D->getIdentifier())
- Out << ' ' << D;
+ Out << ' ' << *D;
- if (D->isDefinition()) {
+ if (D->isCompleteDefinition()) {
// Print the base classes
if (D->getNumBases()) {
Out << " : ";
@@ -694,10 +722,13 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
Visit(*D->decls_begin());
}
-void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
+void DeclPrinter::PrintTemplateParameters(
+ const TemplateParameterList *Params, const TemplateArgumentList *Args = 0) {
+ assert(Params);
+ assert(!Args || Params->size() == Args->size());
+
Out << "template <";
- TemplateParameterList *Params = D->getTemplateParameters();
for (unsigned i = 0, e = Params->size(); i != e; ++i) {
if (i != 0)
Out << ", ";
@@ -716,7 +747,10 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
Out << TTP->getNameAsString();
- if (TTP->hasDefaultArgument()) {
+ if (Args) {
+ Out << " = ";
+ Args->get(i).print(Policy, Out);
+ } else if (TTP->hasDefaultArgument()) {
Out << " = ";
Out << TTP->getDefaultArgument().getAsString(Policy);
};
@@ -732,7 +766,10 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
Out << Name->getName();
}
- if (NTTP->hasDefaultArgument()) {
+ if (Args) {
+ Out << " = ";
+ Args->get(i).print(Policy, Out);
+ } else if (NTTP->hasDefaultArgument()) {
Out << " = ";
NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy,
Indentation);
@@ -745,6 +782,10 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
}
Out << "> ";
+}
+
+void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
+ PrintTemplateParameters(D->getTemplateParameters());
if (const TemplateTemplateParmDecl *TTP =
dyn_cast<TemplateTemplateParmDecl>(D)) {
@@ -757,17 +798,39 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
}
}
+void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ if (PrintInstantiation) {
+ TemplateParameterList *Params = D->getTemplateParameters();
+ for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end();
+ I != E; ++I) {
+ PrintTemplateParameters(Params, (*I)->getTemplateSpecializationArgs());
+ Visit(*I);
+ }
+ }
+
+ return VisitRedeclarableTemplateDecl(D);
+}
+
+void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ if (PrintInstantiation) {
+ TemplateParameterList *Params = D->getTemplateParameters();
+ for (ClassTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end();
+ I != E; ++I) {
+ PrintTemplateParameters(Params, &(*I)->getTemplateArgs());
+ Visit(*I);
+ Out << '\n';
+ }
+ }
+
+ return VisitRedeclarableTemplateDecl(D);
+}
+
//----------------------------------------------------------------------------
// Objective-C declarations
//----------------------------------------------------------------------------
void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) {
- Out << "@class ";
- for (ObjCClassDecl::iterator I = D->begin(), E = D->end();
- I != E; ++I) {
- if (I != D->begin()) Out << ", ";
- Out << I->getInterface();
- }
+ Out << "@class " << *D->getForwardInterfaceDecl();
}
void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
@@ -783,9 +846,9 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
E = OMD->param_end(); PI != E; ++PI) {
// FIXME: selector is missing here!
- pos = name.find_first_of(":", lastPos);
+ pos = name.find_first_of(':', lastPos);
Out << " " << name.substr(lastPos, pos - lastPos);
- Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << *PI;
+ Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << **PI;
lastPos = pos + 1;
}
@@ -807,7 +870,7 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (SID)
- Out << "@implementation " << I << " : " << SID;
+ Out << "@implementation " << I << " : " << *SID;
else
Out << "@implementation " << I;
Out << "\n";
@@ -820,7 +883,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (SID)
- Out << "@interface " << I << " : " << SID;
+ Out << "@interface " << I << " : " << *SID;
else
Out << "@interface " << I;
@@ -829,7 +892,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
if (!Protocols.empty()) {
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end(); I != E; ++I)
- Out << (I == Protocols.begin() ? '<' : ',') << *I;
+ Out << (I == Protocols.begin() ? '<' : ',') << **I;
}
if (!Protocols.empty())
@@ -840,7 +903,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
Indentation += Policy.Indentation;
for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
E = OID->ivar_end(); I != E; ++I) {
- Indent() << (*I)->getType().getAsString(Policy) << ' ' << *I << ";\n";
+ Indent() << (*I)->getType().getAsString(Policy) << ' ' << **I << ";\n";
}
Indentation -= Policy.Indentation;
Out << "}\n";
@@ -857,18 +920,18 @@ void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
E = D->protocol_end();
I != E; ++I) {
if (I != D->protocol_begin()) Out << ", ";
- Out << *I;
+ Out << **I;
}
}
void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
- Out << "@protocol " << PID << '\n';
+ Out << "@protocol " << *PID << '\n';
VisitDeclContext(PID, false);
Out << "@end";
}
void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
- Out << "@implementation " << PID->getClassInterface() << '(' << PID << ")\n";
+ Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n";
VisitDeclContext(PID, false);
Out << "@end";
@@ -876,7 +939,7 @@ void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
}
void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
- Out << "@interface " << PID->getClassInterface() << '(' << PID << ")\n";
+ Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n";
VisitDeclContext(PID, false);
Out << "@end";
@@ -884,8 +947,8 @@ void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
}
void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
- Out << "@compatibility_alias " << AID
- << ' ' << AID->getClassInterface() << ";\n";
+ Out << "@compatibility_alias " << *AID
+ << ' ' << *AID->getClassInterface() << ";\n";
}
/// PrintObjCPropertyDecl - print a property declaration.
@@ -904,58 +967,60 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
ObjCPropertyDecl::OBJC_PR_readonly) {
Out << (first ? ' ' : ',') << "readonly";
first = false;
- }
+ }
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
- Out << (first ? ' ' : ',') << "getter = "
- << PDecl->getGetterName().getAsString();
- first = false;
- }
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
- Out << (first ? ' ' : ',') << "setter = "
- << PDecl->getSetterName().getAsString();
- first = false;
- }
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
+ Out << (first ? ' ' : ',') << "getter = "
+ << PDecl->getGetterName().getAsString();
+ first = false;
+ }
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
+ Out << (first ? ' ' : ',') << "setter = "
+ << PDecl->getSetterName().getAsString();
+ first = false;
+ }
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
- Out << (first ? ' ' : ',') << "assign";
- first = false;
- }
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
+ Out << (first ? ' ' : ',') << "assign";
+ first = false;
+ }
- if (PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_readwrite) {
- Out << (first ? ' ' : ',') << "readwrite";
- first = false;
- }
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_readwrite) {
+ Out << (first ? ' ' : ',') << "readwrite";
+ first = false;
+ }
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
- Out << (first ? ' ' : ',') << "retain";
- first = false;
- }
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
+ Out << (first ? ' ' : ',') << "retain";
+ first = false;
+ }
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
- Out << (first ? ' ' : ',') << "strong";
- first = false;
- }
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
+ Out << (first ? ' ' : ',') << "strong";
+ first = false;
+ }
- if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
- Out << (first ? ' ' : ',') << "copy";
- first = false;
- }
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
+ Out << (first ? ' ' : ',') << "copy";
+ first = false;
+ }
- if (PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_nonatomic) {
- Out << (first ? ' ' : ',') << "nonatomic";
- first = false;
- }
- if (PDecl->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_atomic) {
- Out << (first ? ' ' : ',') << "atomic";
- first = false;
- }
- Out << " )";
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_nonatomic) {
+ Out << (first ? ' ' : ',') << "nonatomic";
+ first = false;
+ }
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_atomic) {
+ Out << (first ? ' ' : ',') << "atomic";
+ first = false;
+ }
+
+ (void) first; // Silence dead store warning due to idiomatic code.
+ Out << " )";
}
- Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl;
+ Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << *PDecl;
}
void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
@@ -963,15 +1028,15 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
Out << "@synthesize ";
else
Out << "@dynamic ";
- Out << PID->getPropertyDecl();
+ Out << *PID->getPropertyDecl();
if (PID->getPropertyIvarDecl())
- Out << '=' << PID->getPropertyIvarDecl();
+ Out << '=' << *PID->getPropertyIvarDecl();
}
void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
Out << "using ";
D->getQualifier()->print(Out, Policy);
- Out << D;
+ Out << *D;
}
void
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index bc375d0ad2d3..558a4ccac96b 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -348,7 +348,7 @@ void ClassTemplateDecl::AddPartialSpecialization(
}
void ClassTemplateDecl::getPartialSpecializations(
- llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) {
+ SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) {
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &PartialSpecs
= getPartialSpecializations();
PS.clear();
@@ -406,7 +406,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
// pack.
ASTContext &Context = getASTContext();
TemplateParameterList *Params = getTemplateParameters();
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+ SmallVector<TemplateArgument, 16> TemplateArgs;
TemplateArgs.resize(Params->size());
GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data());
CommonPtr->InjectedClassNameType
@@ -563,6 +563,24 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true);
}
+FunctionTemplateSpecializationInfo *
+FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD,
+ FunctionTemplateDecl *Template,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentList *TemplateArgs,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation POI) {
+ const ASTTemplateArgumentListInfo *ArgsAsWritten = 0;
+ if (TemplateArgsAsWritten)
+ ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
+ *TemplateArgsAsWritten);
+
+ return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK,
+ TemplateArgs,
+ ArgsAsWritten,
+ POI);
+}
+
//===----------------------------------------------------------------------===//
// ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
@@ -638,15 +656,27 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
SourceRange
ClassTemplateSpecializationDecl::getSourceRange() const {
- if (!ExplicitInfo)
- return SourceRange();
- SourceLocation Begin = getExternLoc();
- if (Begin.isInvalid())
- Begin = getTemplateKeywordLoc();
- SourceLocation End = getRBraceLoc();
- if (End.isInvalid())
- End = getTypeAsWritten()->getTypeLoc().getEndLoc();
- return SourceRange(Begin, End);
+ if (ExplicitInfo) {
+ SourceLocation Begin = getExternLoc();
+ if (Begin.isInvalid())
+ Begin = getTemplateKeywordLoc();
+ SourceLocation End = getRBraceLoc();
+ if (End.isInvalid())
+ End = getTypeAsWritten()->getTypeLoc().getEndLoc();
+ return SourceRange(Begin, End);
+ }
+ else {
+ // No explicit info available.
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ inst_from = getInstantiatedFrom();
+ if (inst_from.isNull())
+ return getSpecializedTemplate()->getSourceRange();
+ if (ClassTemplateDecl *ctd = inst_from.dyn_cast<ClassTemplateDecl*>())
+ return ctd->getSourceRange();
+ return inst_from.get<ClassTemplatePartialSpecializationDecl*>()
+ ->getSourceRange();
+ }
}
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 72c0e9da7f1d..bf647ed7ac35 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -193,8 +193,7 @@ DeclarationName::NameKind DeclarationName::getNameKind() const {
}
// Can't actually get here.
- assert(0 && "This should be unreachable!");
- return Identifier;
+ llvm_unreachable("This should be unreachable!");
}
bool DeclarationName::isDependentName() const {
@@ -209,7 +208,7 @@ std::string DeclarationName::getAsString() const {
return OS.str();
}
-void DeclarationName::printName(llvm::raw_ostream &OS) const {
+void DeclarationName::printName(raw_ostream &OS) const {
switch (getNameKind()) {
case Identifier:
if (const IdentifierInfo *II = getAsIdentifierInfo())
@@ -225,7 +224,7 @@ void DeclarationName::printName(llvm::raw_ostream &OS) const {
case CXXConstructorName: {
QualType ClassType = getCXXNameType();
if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
- OS << ClassRec->getDecl();
+ OS << *ClassRec->getDecl();
else
OS << ClassType.getAsString();
return;
@@ -235,7 +234,7 @@ void DeclarationName::printName(llvm::raw_ostream &OS) const {
OS << '~';
QualType Type = getCXXNameType();
if (const RecordType *Rec = Type->getAs<RecordType>())
- OS << Rec->getDecl();
+ OS << *Rec->getDecl();
else
OS << Type.getAsString();
return;
@@ -266,7 +265,7 @@ void DeclarationName::printName(llvm::raw_ostream &OS) const {
OS << "operator ";
QualType Type = getCXXNameType();
if (const RecordType *Rec = Type->getAs<RecordType>())
- OS << Rec->getDecl();
+ OS << *Rec->getDecl();
else
OS << Type.getAsString();
return;
@@ -276,7 +275,7 @@ void DeclarationName::printName(llvm::raw_ostream &OS) const {
return;
}
- assert(false && "Unexpected declaration name kind");
+ llvm_unreachable("Unexpected declaration name kind");
}
QualType DeclarationName::getCXXNameType() const {
@@ -338,9 +337,8 @@ void *DeclarationName::getFETokenInfoAsVoid() const {
return getCXXLiteralIdentifier()->getFETokenInfo<void>();
default:
- assert(false && "Declaration name has no FETokenInfo");
+ llvm_unreachable("Declaration name has no FETokenInfo");
}
- return 0;
}
void DeclarationName::setFETokenInfo(void *T) {
@@ -364,7 +362,7 @@ void DeclarationName::setFETokenInfo(void *T) {
break;
default:
- assert(false && "Declaration name has no FETokenInfo");
+ llvm_unreachable("Declaration name has no FETokenInfo");
}
}
@@ -562,7 +560,7 @@ std::string DeclarationNameInfo::getAsString() const {
return OS.str();
}
-void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const {
+void DeclarationNameInfo::printName(raw_ostream &OS) const {
switch (Name.getNameKind()) {
case DeclarationName::Identifier:
case DeclarationName::ObjCZeroArgSelector:
@@ -588,7 +586,7 @@ void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const {
Name.printName(OS);
return;
}
- assert(false && "Unexpected declaration name kind");
+ llvm_unreachable("Unexpected declaration name kind");
}
SourceLocation DeclarationNameInfo::getEndLoc() const {
@@ -621,6 +619,5 @@ SourceLocation DeclarationNameInfo::getEndLoc() const {
case DeclarationName::CXXUsingDirective:
return NameLoc;
}
- assert(false && "Unexpected declaration name kind");
- return SourceLocation();
+ llvm_unreachable("Unexpected declaration name kind");
}
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index dfe0119f597d..2568adaa5a44 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -53,9 +53,9 @@ enum NodeState {
};
struct Node {
- llvm::StringRef Name;
+ StringRef Name;
NodeState State;
- Node(llvm::StringRef name) : Name(name), State(NS_Attrs) {}
+ Node(StringRef name) : Name(name), State(NS_Attrs) {}
bool isDoneWithAttrs() const { return State != NS_Attrs; }
};
@@ -159,7 +159,7 @@ template <class Impl> struct XMLTypeVisitor {
#undef DISPATCH
};
-static llvm::StringRef getTypeKindName(Type *T) {
+static StringRef getTypeKindName(Type *T) {
switch (T->getTypeClass()) {
#define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
#define ABSTRACT_TYPE(DERIVED, BASE)
@@ -172,11 +172,11 @@ static llvm::StringRef getTypeKindName(Type *T) {
struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
public XMLTypeVisitor<XMLDumper> {
- llvm::raw_ostream &out;
+ raw_ostream &out;
ASTContext &Context;
- llvm::SmallVector<Node, 16> Stack;
+ SmallVector<Node, 16> Stack;
unsigned Indent;
- explicit XMLDumper(llvm::raw_ostream &OS, ASTContext &context)
+ explicit XMLDumper(raw_ostream &OS, ASTContext &context)
: out(OS), Context(context), Indent(0) {}
void indent() {
@@ -185,7 +185,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
/// Push a new node on the stack.
- void push(llvm::StringRef name) {
+ void push(StringRef name) {
if (!Stack.empty()) {
assert(Stack.back().isDoneWithAttrs());
if (Stack.back().State == NS_LazyChildren) {
@@ -200,7 +200,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
/// Set the given attribute to the given value.
- void set(llvm::StringRef attr, llvm::StringRef value) {
+ void set(StringRef attr, StringRef value) {
assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
}
@@ -226,7 +226,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
//---- General utilities -------------------------------------------//
- void setPointer(llvm::StringRef prop, const void *p) {
+ void setPointer(StringRef prop, const void *p) {
llvm::SmallString<10> buffer;
llvm::raw_svector_ostream os(buffer);
os << p;
@@ -238,11 +238,11 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
setPointer("ptr", p);
}
- void setInteger(llvm::StringRef prop, const llvm::APSInt &v) {
+ void setInteger(StringRef prop, const llvm::APSInt &v) {
set(prop, v.toString(10));
}
- void setInteger(llvm::StringRef prop, unsigned n) {
+ void setInteger(StringRef prop, unsigned n) {
llvm::SmallString<10> buffer;
llvm::raw_svector_ostream os(buffer);
os << n;
@@ -250,7 +250,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
set(prop, buffer);
}
- void setFlag(llvm::StringRef prop, bool flag) {
+ void setFlag(StringRef prop, bool flag) {
if (flag) set(prop, "true");
}
@@ -268,7 +268,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
class TemporaryContainer {
XMLDumper &Dumper;
public:
- TemporaryContainer(XMLDumper &dumper, llvm::StringRef name)
+ TemporaryContainer(XMLDumper &dumper, StringRef name)
: Dumper(dumper) {
Dumper.push(name);
Dumper.completeAttrs();
@@ -303,7 +303,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
completeAttrs();
pop();
}
- void visitDeclRef(llvm::StringRef Name, Decl *D) {
+ void visitDeclRef(StringRef Name, Decl *D) {
TemporaryContainer C(*this, Name);
if (D) visitDeclRef(D);
}
@@ -423,7 +423,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
// LinkageSpecDecl
void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
- llvm::StringRef lang = "";
+ StringRef lang = "";
switch (D->getLanguage()) {
case LinkageSpecDecl::lang_c: lang = "C"; break;
case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
@@ -742,8 +742,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
// ObjCClassDecl
void visitObjCClassDeclChildren(ObjCClassDecl *D) {
- for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I)
- visitDeclRef(I->getInterface());
+ visitDeclRef(D->getForwardInterfaceDecl());
}
// ObjCInterfaceDecl
@@ -860,7 +859,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
// ObjCIvarDecl
- void setAccessControl(llvm::StringRef prop, ObjCIvarDecl::AccessControl AC) {
+ void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) {
switch (AC) {
case ObjCIvarDecl::None: return set(prop, "none");
case ObjCIvarDecl::Private: return set(prop, "private");
@@ -1031,13 +1030,13 @@ void Decl::dumpXML() const {
dumpXML(llvm::errs());
}
-void Decl::dumpXML(llvm::raw_ostream &out) const {
+void Decl::dumpXML(raw_ostream &out) const {
XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
}
#else /* ifndef NDEBUG */
void Decl::dumpXML() const {}
-void Decl::dumpXML(llvm::raw_ostream &out) const {}
+void Decl::dumpXML(raw_ostream &out) const {}
#endif
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 4611ae369969..b0bcfe09f6dc 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -130,57 +130,6 @@ SourceLocation Expr::getExprLoc() const {
// Primary Expressions.
//===----------------------------------------------------------------------===//
-void ExplicitTemplateArgumentList::initializeFrom(
- const TemplateArgumentListInfo &Info) {
- LAngleLoc = Info.getLAngleLoc();
- RAngleLoc = Info.getRAngleLoc();
- NumTemplateArgs = Info.size();
-
- TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
- for (unsigned i = 0; i != NumTemplateArgs; ++i)
- new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
-}
-
-void ExplicitTemplateArgumentList::initializeFrom(
- const TemplateArgumentListInfo &Info,
- bool &Dependent,
- bool &InstantiationDependent,
- bool &ContainsUnexpandedParameterPack) {
- LAngleLoc = Info.getLAngleLoc();
- RAngleLoc = Info.getRAngleLoc();
- NumTemplateArgs = Info.size();
-
- TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
- for (unsigned i = 0; i != NumTemplateArgs; ++i) {
- Dependent = Dependent || Info[i].getArgument().isDependent();
- InstantiationDependent = InstantiationDependent ||
- Info[i].getArgument().isInstantiationDependent();
- ContainsUnexpandedParameterPack
- = ContainsUnexpandedParameterPack ||
- Info[i].getArgument().containsUnexpandedParameterPack();
-
- new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
- }
-}
-
-void ExplicitTemplateArgumentList::copyInto(
- TemplateArgumentListInfo &Info) const {
- Info.setLAngleLoc(LAngleLoc);
- Info.setRAngleLoc(RAngleLoc);
- for (unsigned I = 0; I != NumTemplateArgs; ++I)
- 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 sizeFor(Info.size());
-}
-
/// \brief Compute the type-, value-, and instantiation-dependence of a
/// declaration reference
/// based on the declaration being referenced.
@@ -325,7 +274,8 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc,
if (InstantiationDependent)
setInstantiationDependent(true);
}
-
+ DeclRefExprBits.HadMultipleCandidates = 0;
+
computeDependence();
}
@@ -360,7 +310,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
if (FoundD)
Size += sizeof(NamedDecl *);
if (TemplateArgs)
- Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
+ Size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs);
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(QualifierLoc, D, NameInfo, FoundD, TemplateArgs,
@@ -378,7 +328,7 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context,
if (HasFoundDecl)
Size += sizeof(NamedDecl *);
if (HasExplicitTemplateArgs)
- Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ Size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs);
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(EmptyShell());
@@ -463,7 +413,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
// For incorrect code, there might not be an ObjCInterfaceDecl. Do
// a null check to avoid a crash.
if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
- Out << ID;
+ Out << *ID;
if (const ObjCCategoryImplDecl *CID =
dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext()))
@@ -532,9 +482,8 @@ double FloatingLiteral::getValueAsApproximateDouble() const {
return V.convertToDouble();
}
-StringLiteral *StringLiteral::Create(ASTContext &C, llvm::StringRef Str,
- bool Wide,
- bool Pascal, QualType Ty,
+StringLiteral *StringLiteral::Create(ASTContext &C, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
const SourceLocation *Loc,
unsigned NumStrs) {
// Allocate enough space for the StringLiteral plus an array of locations for
@@ -549,7 +498,7 @@ StringLiteral *StringLiteral::Create(ASTContext &C, llvm::StringRef Str,
memcpy(AStrData, Str.data(), Str.size());
SL->StrData = AStrData;
SL->ByteLength = Str.size();
- SL->IsWide = Wide;
+ SL->Kind = Kind;
SL->IsPascal = Pascal;
SL->TokLocs[0] = Loc[0];
SL->NumConcatenated = NumStrs;
@@ -570,7 +519,7 @@ StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) {
return SL;
}
-void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
+void StringLiteral::setString(ASTContext &C, StringRef Str) {
char *AStrData = new (C, 1) char[Str.size()];
memcpy(AStrData, Str.data(), Str.size());
StrData = AStrData;
@@ -587,8 +536,8 @@ void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
SourceLocation StringLiteral::
getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
const LangOptions &Features, const TargetInfo &Target) const {
- assert(!isWide() && "This doesn't work for wide strings yet");
-
+ assert(Kind == StringLiteral::Ascii && "This only works for ASCII strings");
+
// Loop over all of the tokens in this string until we find the one that
// contains the byte we're looking for.
unsigned TokNo = 0;
@@ -604,7 +553,7 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
// Re-lex the token to get its length and original spelling.
std::pair<FileID, unsigned> LocInfo =SM.getDecomposedLoc(StrTokSpellingLoc);
bool Invalid = false;
- llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
+ StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
if (Invalid)
return StrTokSpellingLoc;
@@ -647,7 +596,7 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
/// corresponds to, e.g. "sizeof" or "[pre]++".
const char *UnaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
- default: assert(0 && "Unknown unary operator");
+ default: llvm_unreachable("Unknown unary operator");
case UO_PostInc: return "++";
case UO_PostDec: return "--";
case UO_PreInc: return "++";
@@ -667,7 +616,7 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) {
UnaryOperatorKind
UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) {
switch (OO) {
- default: assert(false && "No unary operator for overloaded function");
+ default: llvm_unreachable("No unary operator for overloaded function");
case OO_PlusPlus: return Postfix ? UO_PostInc : UO_PreInc;
case OO_MinusMinus: return Postfix ? UO_PostDec : UO_PreDec;
case OO_Amp: return UO_AddrOf;
@@ -771,7 +720,13 @@ CallExpr::CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs,
}
Decl *CallExpr::getCalleeDecl() {
- Expr *CEE = getCallee()->IgnoreParenCasts();
+ Expr *CEE = getCallee()->IgnoreParenImpCasts();
+
+ while (SubstNonTypeTemplateParmExpr *NTTP
+ = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
+ CEE = NTTP->getReplacement()->IgnoreParenCasts();
+ }
+
// If we're calling a dereference, look at the pointer instead.
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) {
if (BO->isPtrMemOp())
@@ -947,7 +902,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
Size += sizeof(MemberNameQualifier);
if (targs)
- Size += ExplicitTemplateArgumentList::sizeFor(*targs);
+ Size += ASTTemplateArgumentListInfo::sizeFor(*targs);
void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo,
@@ -1008,6 +963,94 @@ SourceRange MemberExpr::getSourceRange() const {
return SourceRange(StartLoc, EndLoc);
}
+void CastExpr::CheckCastConsistency() const {
+ switch (getCastKind()) {
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_BaseToDerived:
+ case CK_BaseToDerivedMemberPointer:
+ assert(!path_empty() && "Cast kind should have a base path!");
+ break;
+
+ case CK_CPointerToObjCPointerCast:
+ assert(getType()->isObjCObjectPointerType());
+ assert(getSubExpr()->getType()->isPointerType());
+ goto CheckNoBasePath;
+
+ case CK_BlockPointerToObjCPointerCast:
+ assert(getType()->isObjCObjectPointerType());
+ assert(getSubExpr()->getType()->isBlockPointerType());
+ goto CheckNoBasePath;
+
+ case CK_BitCast:
+ // Arbitrary casts to C pointer types count as bitcasts.
+ // Otherwise, we should only have block and ObjC pointer casts
+ // here if they stay within the type kind.
+ if (!getType()->isPointerType()) {
+ assert(getType()->isObjCObjectPointerType() ==
+ getSubExpr()->getType()->isObjCObjectPointerType());
+ assert(getType()->isBlockPointerType() ==
+ getSubExpr()->getType()->isBlockPointerType());
+ }
+ goto CheckNoBasePath;
+
+ case CK_AnyPointerToBlockPointerCast:
+ assert(getType()->isBlockPointerType());
+ assert(getSubExpr()->getType()->isAnyPointerType() &&
+ !getSubExpr()->getType()->isBlockPointerType());
+ goto CheckNoBasePath;
+
+ // These should not have an inheritance path.
+ case CK_Dynamic:
+ case CK_ToUnion:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
+ case CK_NullToMemberPointer:
+ case CK_NullToPointer:
+ case CK_ConstructorConversion:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_ToVoid:
+ case CK_VectorSplat:
+ case CK_IntegralCast:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingCast:
+ case CK_ObjCObjectLValueCast:
+ case CK_FloatingRealToComplex:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex:
+ case CK_ARCProduceObject:
+ case CK_ARCConsumeObject:
+ case CK_ARCReclaimReturnedObject:
+ case CK_ARCExtendBlockObject:
+ assert(!getType()->isBooleanType() && "unheralded conversion to bool");
+ goto CheckNoBasePath;
+
+ case CK_Dependent:
+ case CK_LValueToRValue:
+ case CK_GetObjCProperty:
+ case CK_NoOp:
+ case CK_PointerToBoolean:
+ case CK_IntegralToBoolean:
+ case CK_FloatingToBoolean:
+ case CK_MemberPointerToBoolean:
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToBoolean:
+ case CK_LValueBitCast: // -> bool&
+ case CK_UserDefinedConversion: // operator bool()
+ CheckNoBasePath:
+ assert(path_empty() && "Cast kind should not have a base path!");
+ break;
+ }
+}
+
const char *CastExpr::getCastKindName() const {
switch (getCastKind()) {
case CK_Dependent:
@@ -1072,8 +1115,10 @@ const char *CastExpr::getCastKindName() const {
return "FloatingToBoolean";
case CK_MemberPointerToBoolean:
return "MemberPointerToBoolean";
- case CK_AnyPointerToObjCPointerCast:
- return "AnyPointerToObjCPointerCast";
+ case CK_CPointerToObjCPointerCast:
+ return "CPointerToObjCPointerCast";
+ case CK_BlockPointerToObjCPointerCast:
+ return "BlockPointerToObjCPointerCast";
case CK_AnyPointerToBlockPointerCast:
return "AnyPointerToBlockPointerCast";
case CK_ObjCObjectLValueCast:
@@ -1098,12 +1143,14 @@ const char *CastExpr::getCastKindName() const {
return "IntegralComplexCast";
case CK_IntegralComplexToFloatingComplex:
return "IntegralComplexToFloatingComplex";
- case CK_ObjCConsumeObject:
- return "ObjCConsumeObject";
- case CK_ObjCProduceObject:
- return "ObjCProduceObject";
- case CK_ObjCReclaimReturnedObject:
- return "ObjCReclaimReturnedObject";
+ case CK_ARCConsumeObject:
+ return "ARCConsumeObject";
+ case CK_ARCProduceObject:
+ return "ARCProduceObject";
+ case CK_ARCReclaimReturnedObject:
+ return "ARCReclaimReturnedObject";
+ case CK_ARCExtendBlockObject:
+ return "ARCCExtendBlockObject";
}
llvm_unreachable("Unhandled cast kind!");
@@ -1243,7 +1290,7 @@ const char *BinaryOperator::getOpcodeStr(Opcode Op) {
BinaryOperatorKind
BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
switch (OO) {
- default: assert(false && "Not an overloadable binary operator");
+ default: llvm_unreachable("Not an overloadable binary operator");
case OO_Plus: return BO_Add;
case OO_Minus: return BO_Sub;
case OO_Star: return BO_Mul;
@@ -1491,6 +1538,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
}
case CompoundAssignOperatorClass:
case VAArgExprClass:
+ case AtomicExprClass:
return false;
case ConditionalOperatorClass: {
@@ -1525,8 +1573,24 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
R2 = cast<ArraySubscriptExpr>(this)->getRHS()->getSourceRange();
return true;
+ case CXXOperatorCallExprClass: {
+ // We warn about operator== and operator!= even when user-defined operator
+ // overloads as there is no reasonable way to define these such that they
+ // have non-trivial, desirable side-effects. See the -Wunused-comparison
+ // warning: these operators are commonly typo'ed, and so warning on them
+ // provides additional value as well. If this list is updated,
+ // DiagnoseUnusedComparison should be as well.
+ const CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(this);
+ if (Op->getOperator() == OO_EqualEqual ||
+ Op->getOperator() == OO_ExclaimEqual) {
+ Loc = Op->getOperatorLoc();
+ R1 = Op->getSourceRange();
+ return true;
+ }
+
+ // Fallthrough for generic call handling.
+ }
case CallExprClass:
- case CXXOperatorCallExprClass:
case CXXMemberCallExprClass: {
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
@@ -1666,8 +1730,15 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
->isOBJCGCCandidate(Ctx);
case CStyleCastExprClass:
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
+ case BlockDeclRefExprClass:
case DeclRefExprClass: {
- const Decl *D = cast<DeclRefExpr>(E)->getDecl();
+
+ const Decl *D;
+ if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E))
+ D = BDRE->getDecl();
+ else
+ D = cast<DeclRefExpr>(E)->getDecl();
+
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasGlobalStorage())
return true;
@@ -2024,7 +2095,11 @@ Expr *Expr::IgnoreParenCasts() {
E = Materialize->GetTemporaryExpr();
continue;
}
-
+ if (SubstNonTypeTemplateParmExpr *NTTP
+ = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
+ E = NTTP->getReplacement();
+ continue;
+ }
return E;
}
}
@@ -2058,6 +2133,10 @@ Expr *Expr::IgnoreParenLValueCasts() {
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
continue;
+ } else if (SubstNonTypeTemplateParmExpr *NTTP
+ = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
+ E = NTTP->getReplacement();
+ continue;
}
break;
}
@@ -2092,6 +2171,11 @@ Expr *Expr::IgnoreParenImpCasts() {
E = Materialize->GetTemporaryExpr();
continue;
}
+ if (SubstNonTypeTemplateParmExpr *NTTP
+ = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
+ E = NTTP->getReplacement();
+ continue;
+ }
return E;
}
}
@@ -2149,6 +2233,12 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
}
}
+ if (SubstNonTypeTemplateParmExpr *NTTP
+ = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
+ E = NTTP->getReplacement();
+ continue;
+ }
+
return E;
}
}
@@ -2397,7 +2487,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
break;
case MaterializeTemporaryExprClass:
- return llvm::cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
+ return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
->isConstantInitializer(Ctx, false);
}
return isEvaluatable(Ctx);
@@ -2414,9 +2504,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
if (isValueDependent()) {
switch (NPC) {
case NPC_NeverValueDependent:
- assert(false && "Unexpected value dependent expression!");
- // If the unthinkable happens, fall through to the safest alternative.
-
+ llvm_unreachable("Unexpected value dependent expression!");
case NPC_ValueDependentIsNull:
if (isTypeDependent() || getType()->isIntegralType(Ctx))
return NPCK_ZeroInteger;
@@ -2576,7 +2664,7 @@ unsigned ExtVectorElementExpr::getNumElements() const {
bool ExtVectorElementExpr::containsDuplicateElements() const {
// FIXME: Refactor this code to an accessor on the AST node which returns the
// "type" of component access, and share with code below and in Sema.
- llvm::StringRef Comp = Accessor->getName();
+ StringRef Comp = Accessor->getName();
// Halving swizzles do not contain duplicate elements.
if (Comp == "hi" || Comp == "lo" || Comp == "even" || Comp == "odd")
@@ -2587,7 +2675,7 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
Comp = Comp.substr(1);
for (unsigned i = 0, e = Comp.size(); i != e; ++i)
- if (Comp.substr(i + 1).find(Comp[i]) != llvm::StringRef::npos)
+ if (Comp.substr(i + 1).find(Comp[i]) != StringRef::npos)
return true;
return false;
@@ -2595,8 +2683,8 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
void ExtVectorElementExpr::getEncodedElementAccess(
- llvm::SmallVectorImpl<unsigned> &Elts) const {
- llvm::StringRef Comp = Accessor->getName();
+ SmallVectorImpl<unsigned> &Elts) const {
+ StringRef Comp = Accessor->getName();
if (Comp[0] == 's' || Comp[0] == 'S')
Comp = Comp.substr(1);
@@ -2630,23 +2718,23 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
- SourceLocation SelLoc,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RBracLoc)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
/*TypeDependent=*/false, /*ValueDependent=*/false,
/*InstantiationDependent=*/false,
/*ContainsUnexpandedParameterPack=*/false),
- NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass),
- HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
- SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+ Kind(IsInstanceSuper? SuperInstance : SuperClass),
+ HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc),
+ LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
+ initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(SuperType.getAsOpaquePtr());
- if (NumArgs)
- memcpy(getArgs(), Args, NumArgs * sizeof(Expr *));
}
ObjCMessageExpr::ObjCMessageExpr(QualType T,
@@ -2654,33 +2742,22 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
- SourceLocation SelLoc,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RBracLoc)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
T->isDependentType(), T->isInstantiationDependentType(),
T->containsUnexpandedParameterPack()),
- NumArgs(NumArgs), Kind(Class),
- HasMethod(Method != 0), IsDelegateInitCall(false),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
- SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+ Kind(Class),
+ HasMethod(Method != 0), IsDelegateInitCall(false),
+ LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
+ initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver);
- Expr **MyArgs = getArgs();
- for (unsigned I = 0; I != NumArgs; ++I) {
- if (Args[I]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (Args[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Args[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Args[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
- MyArgs[I] = Args[I];
- }
}
ObjCMessageExpr::ObjCMessageExpr(QualType T,
@@ -2688,23 +2765,31 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
- SourceLocation SelLoc,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RBracLoc)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(),
Receiver->isTypeDependent(),
Receiver->isInstantiationDependent(),
Receiver->containsUnexpandedParameterPack()),
- NumArgs(NumArgs), Kind(Instance),
- HasMethod(Method != 0), IsDelegateInitCall(false),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
- SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+ Kind(Instance),
+ HasMethod(Method != 0), IsDelegateInitCall(false),
+ LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
+ initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver);
+}
+
+void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK) {
+ setNumArgs(Args.size());
Expr **MyArgs = getArgs();
- for (unsigned I = 0; I != NumArgs; ++I) {
+ for (unsigned I = 0; I != Args.size(); ++I) {
if (Args[I]->isTypeDependent())
ExprBits.TypeDependent = true;
if (Args[I]->isValueDependent())
@@ -2716,6 +2801,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
MyArgs[I] = Args[I];
}
+
+ SelLocsKind = SelLocsK;
+ if (SelLocsK == SelLoc_NonStandard)
+ std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@@ -2725,16 +2814,15 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
- SourceLocation SelLoc,
+ ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RBracLoc) {
- unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
- NumArgs * sizeof(Expr *);
- void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
+ SelectorLocationsKind SelLocsK;
+ ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper,
- SuperType, Sel, SelLoc, Method, Args,NumArgs,
- RBracLoc);
+ SuperType, Sel, SelLocs, SelLocsK,
+ Method, Args, RBracLoc);
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@@ -2742,15 +2830,14 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
- SourceLocation SelLoc,
+ ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RBracLoc) {
- unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
- NumArgs * sizeof(Expr *);
- void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
- return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc,
- Method, Args, NumArgs, RBracLoc);
+ SelectorLocationsKind SelLocsK;
+ ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
+ return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
+ SelLocs, SelLocsK, Method, Args, RBracLoc);
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@@ -2758,25 +2845,50 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
- SourceLocation SelLoc,
+ ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RBracLoc) {
- unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
- NumArgs * sizeof(Expr *);
- void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
- return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc,
- Method, Args, NumArgs, RBracLoc);
+ SelectorLocationsKind SelLocsK;
+ ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
+ return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
+ SelLocs, SelLocsK, Method, Args, RBracLoc);
}
ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context,
- unsigned NumArgs) {
- unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
- NumArgs * sizeof(Expr *);
- void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
+ unsigned NumArgs,
+ unsigned NumStoredSelLocs) {
+ ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs);
return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs);
}
+ObjCMessageExpr *ObjCMessageExpr::alloc(ASTContext &C,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBraceLoc,
+ ArrayRef<SourceLocation> SelLocs,
+ Selector Sel,
+ SelectorLocationsKind &SelLocsK) {
+ SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, RBraceLoc);
+ unsigned NumStoredSelLocs = (SelLocsK == SelLoc_NonStandard) ? SelLocs.size()
+ : 0;
+ return alloc(C, Args.size(), NumStoredSelLocs);
+}
+
+ObjCMessageExpr *ObjCMessageExpr::alloc(ASTContext &C,
+ unsigned NumArgs,
+ unsigned NumStoredSelLocs) {
+ unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
+ NumArgs * sizeof(Expr *) + NumStoredSelLocs * sizeof(SourceLocation);
+ return (ObjCMessageExpr *)C.Allocate(Size,
+ llvm::AlignOf<ObjCMessageExpr>::Alignment);
+}
+
+void ObjCMessageExpr::getSelectorLocs(
+ SmallVectorImpl<SourceLocation> &SelLocs) const {
+ for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
+ SelLocs.push_back(getSelectorLoc(i));
+}
+
SourceRange ObjCMessageExpr::getReceiverRange() const {
switch (getReceiverKind()) {
case Instance:
@@ -2830,7 +2942,7 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
return 0;
}
-llvm::StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
+StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
switch (getBridgeKind()) {
case OBC_Bridge:
return "__bridge";
@@ -2844,7 +2956,7 @@ llvm::StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
}
bool ChooseExpr::isConditionTrue(const ASTContext &C) const {
- return getCond()->EvaluateAsInt(C) != 0;
+ return getCond()->EvaluateKnownConstInt(C) != 0;
}
ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
@@ -3203,3 +3315,24 @@ BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
ExprBits.ValueDependent = ValueDependent;
ExprBits.InstantiationDependent = InstantiationDependent;
}
+
+
+AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr,
+ QualType t, AtomicOp op, SourceLocation RP)
+ : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary,
+ false, false, false, false),
+ NumSubExprs(nexpr), BuiltinLoc(BLoc), RParenLoc(RP), Op(op)
+{
+ for (unsigned i = 0; i < nexpr; i++) {
+ if (args[i]->isTypeDependent())
+ ExprBits.TypeDependent = true;
+ if (args[i]->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (args[i]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (args[i]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ SubExprs[i] = args[i];
+ }
+}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index f92afffb5851..ad5ec8b8331a 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -49,6 +49,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
SourceRange TypeIdParens, Expr *arraySize,
CXXConstructorDecl *constructor, bool initializer,
Expr **constructorArgs, unsigned numConsArgs,
+ bool HadMultipleCandidates,
FunctionDecl *operatorDelete,
bool usualArrayDeleteWantsSize, QualType ty,
TypeSourceInfo *AllocatedTypeInfo,
@@ -61,6 +62,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
ty->containsUnexpandedParameterPack()),
GlobalNew(globalNew), Initializer(initializer),
UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize),
+ HadMultipleCandidates(HadMultipleCandidates),
SubExprs(0), OperatorNew(operatorNew),
OperatorDelete(operatorDelete), Constructor(constructor),
AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens),
@@ -202,7 +204,7 @@ UnresolvedLookupExpr::Create(ASTContext &C,
UnresolvedSetIterator End)
{
void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) +
- ExplicitTemplateArgumentList::sizeFor(Args));
+ ASTTemplateArgumentListInfo::sizeFor(Args));
return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo,
ADL, /*Overload*/ true, &Args,
Begin, End, /*StdIsAssociated=*/false);
@@ -213,7 +215,7 @@ UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs) {
std::size_t size = sizeof(UnresolvedLookupExpr);
if (HasExplicitTemplateArgs)
- size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>());
UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
@@ -332,7 +334,7 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
bool ContainsUnexpandedParameterPack
= ExprBits.ContainsUnexpandedParameterPack;
- reinterpret_cast<ExplicitTemplateArgumentList*>(this+1)
+ reinterpret_cast<ASTTemplateArgumentListInfo*>(this+1)
->initializeFrom(*Args, Dependent, InstantiationDependent,
ContainsUnexpandedParameterPack);
@@ -347,7 +349,7 @@ DependentScopeDeclRefExpr::Create(ASTContext &C,
const TemplateArgumentListInfo *Args) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (Args)
- size += ExplicitTemplateArgumentList::sizeFor(*Args);
+ size += ASTTemplateArgumentListInfo::sizeFor(*Args);
void *Mem = C.Allocate(size);
return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc,
NameInfo, Args);
@@ -359,7 +361,7 @@ DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
unsigned NumTemplateArgs) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (HasExplicitTemplateArgs)
- size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size);
DependentScopeDeclRefExpr *E
= new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
@@ -628,11 +630,13 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
Expr **Args,
unsigned NumArgs,
SourceRange parenRange,
+ bool HadMultipleCandidates,
bool ZeroInitialization)
: CXXConstructExpr(C, CXXTemporaryObjectExprClass,
Type->getType().getNonReferenceType(),
Type->getTypeLoc().getBeginLoc(),
- Cons, false, Args, NumArgs, ZeroInitialization,
+ Cons, false, Args, NumArgs,
+ HadMultipleCandidates, ZeroInitialization,
CXXConstructExpr::CK_Complete, parenRange),
Type(Type) {
}
@@ -646,11 +650,13 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
+ bool HadMultipleCandidates,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenRange) {
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D,
- Elidable, Args, NumArgs, ZeroInitialization,
+ Elidable, Args, NumArgs,
+ HadMultipleCandidates, ZeroInitialization,
ConstructKind, ParenRange);
}
@@ -658,16 +664,18 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool elidable,
Expr **args, unsigned numargs,
- bool ZeroInitialization,
+ bool HadMultipleCandidates,
+ bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenRange)
: Expr(SC, T, VK_RValue, OK_Ordinary,
T->isDependentType(), T->isDependentType(),
T->isInstantiationDependentType(),
T->containsUnexpandedParameterPack()),
- Constructor(D), Loc(Loc), ParenRange(ParenRange), Elidable(elidable),
- ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind),
- Args(0), NumArgs(numargs)
+ Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs),
+ Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates),
+ ZeroInitialization(ZeroInitialization),
+ ConstructKind(ConstructKind), Args(0)
{
if (NumArgs) {
Args = new (C) Stmt*[NumArgs];
@@ -838,7 +846,7 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C,
std::size_t size = sizeof(CXXDependentScopeMemberExpr);
if (TemplateArgs)
- size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
+ size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>());
return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType,
@@ -859,7 +867,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
DeclarationNameInfo());
std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
- ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>());
CXXDependentScopeMemberExpr *E
= new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(),
@@ -947,7 +955,7 @@ UnresolvedMemberExpr::Create(ASTContext &C,
UnresolvedSetIterator End) {
std::size_t size = sizeof(UnresolvedMemberExpr);
if (TemplateArgs)
- size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
+ size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>());
return new (Mem) UnresolvedMemberExpr(C,
@@ -961,7 +969,7 @@ UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs) {
std::size_t size = sizeof(UnresolvedMemberExpr);
if (HasExplicitTemplateArgs)
- size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>());
UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index e7888a6aa7b3..49c68213aa43 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -162,6 +162,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::SubstNonTypeTemplateParmPackExprClass:
case Expr::AsTypeExprClass:
case Expr::ObjCIndirectCopyRestoreExprClass:
+ case Expr::AtomicExprClass:
return Cl::CL_PRValue;
// Next come the complicated cases.
@@ -393,7 +394,7 @@ static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) {
// 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
+ // if the result type is an rvalue reference to object type, and a prvalue
// otherwise.
if (T->isLValueReferenceType())
return Cl::CL_LValue;
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 786155af281d..df75bc8a735f 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -59,6 +59,8 @@ namespace {
EvalInfo(const ASTContext &ctx, Expr::EvalResult &evalresult)
: Ctx(ctx), EvalResult(evalresult) {}
+
+ const LangOptions &getLangOpts() { return Ctx.getLangOptions(); }
};
struct ComplexValue {
@@ -378,18 +380,22 @@ private:
RetTy DerivedError(const Expr *E) {
return static_cast<Derived*>(this)->Error(E);
}
+ RetTy DerivedValueInitialization(const Expr *E) {
+ return static_cast<Derived*>(this)->ValueInitialization(E);
+ }
protected:
EvalInfo &Info;
typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy;
typedef ExprEvaluatorBase ExprEvaluatorBaseTy;
+ RetTy ValueInitialization(const Expr *E) { return DerivedError(E); }
+
public:
ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
RetTy VisitStmt(const Stmt *) {
- assert(0 && "Expression evaluator should not be called on stmts");
- return DerivedError(0);
+ llvm_unreachable("Expression evaluator should not be called on stmts");
}
RetTy VisitExpr(const Expr *E) {
return DerivedError(E);
@@ -436,6 +442,23 @@ public:
: DerivedError(E));
return DerivedSuccess(*value, E);
}
+
+ RetTy VisitInitListExpr(const InitListExpr *E) {
+ if (Info.getLangOpts().CPlusPlus0x) {
+ if (E->getNumInits() == 0)
+ return DerivedValueInitialization(E);
+ if (E->getNumInits() == 1)
+ return StmtVisitorTy::Visit(E->getInit(0));
+ }
+ return DerivedError(E);
+ }
+ RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
+ return DerivedValueInitialization(E);
+ }
+ RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
+ return DerivedValueInitialization(E);
+ }
+
};
}
@@ -447,6 +470,7 @@ namespace {
class LValueExprEvaluator
: public ExprEvaluatorBase<LValueExprEvaluator, bool> {
LValue &Result;
+ const Decl *PrevDecl;
bool Success(const Expr *E) {
Result.Base = E;
@@ -456,7 +480,7 @@ class LValueExprEvaluator
public:
LValueExprEvaluator(EvalInfo &info, LValue &Result) :
- ExprEvaluatorBaseTy(info), Result(Result) {}
+ ExprEvaluatorBaseTy(info), Result(Result), PrevDecl(0) {}
bool Success(const APValue &V, const Expr *E) {
Result.setFrom(V);
@@ -481,9 +505,13 @@ public:
return false;
case CK_NoOp:
+ case CK_LValueBitCast:
return Visit(E->getSubExpr());
+
+ // FIXME: Support CK_DerivedToBase and friends.
}
}
+
// FIXME: Missing: __real__, __imag__
};
@@ -501,10 +529,16 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
return Success(E);
// Reference parameters can refer to anything even if they have an
// "initializer" in the form of a default argument.
- if (!isa<ParmVarDecl>(VD))
+ if (!isa<ParmVarDecl>(VD)) {
// FIXME: Check whether VD might be overridden!
+
+ // Check for recursive initializers of references.
+ if (PrevDecl == VD)
+ return Error(E);
+ PrevDecl = VD;
if (const Expr *Init = VD->getAnyInitializer())
return Visit(Init);
+ }
}
return ExprEvaluatorBaseTy::VisitDeclRefExpr(E);
@@ -585,6 +619,9 @@ public:
bool Error(const Stmt *S) {
return false;
}
+ bool ValueInitialization(const Expr *E) {
+ return Success((Expr*)0);
+ }
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitCastExpr(const CastExpr* E);
@@ -599,10 +636,8 @@ public:
return Success(E);
return false;
}
- bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E)
- { return Success((Expr*)0); }
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
- { return Success((Expr*)0); }
+ { return ValueInitialization(E); }
// FIXME: Missing: @protocol, @selector
};
@@ -667,7 +702,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
case CK_NoOp:
case CK_BitCast:
- case CK_AnyPointerToObjCPointerCast:
+ case CK_CPointerToObjCPointerCast:
+ case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
return Visit(SubExpr);
@@ -761,11 +797,11 @@ namespace {
APValue Success(const APValue &V, const Expr *E) { return V; }
APValue Error(const Expr *E) { return APValue(); }
+ APValue ValueInitialization(const Expr *E)
+ { return GetZeroVector(E->getType()); }
APValue VisitUnaryReal(const UnaryOperator *E)
{ return Visit(E->getSubExpr()); }
- APValue VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E)
- { return GetZeroVector(E->getType()); }
APValue VisitCastExpr(const CastExpr* E);
APValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
APValue VisitInitListExpr(const InitListExpr *E);
@@ -812,7 +848,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
}
// Splat and create vector APValue.
- llvm::SmallVector<APValue, 4> Elts(NElts, Result);
+ SmallVector<APValue, 4> Elts(NElts, Result);
return APValue(&Elts[0], Elts.size());
}
case CK_BitCast: {
@@ -829,7 +865,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
assert((EltTy->isIntegerType() || EltTy->isRealFloatingType()) &&
"Vectors must be composed of ints or floats");
- llvm::SmallVector<APValue, 4> Elts;
+ SmallVector<APValue, 4> Elts;
for (unsigned i = 0; i != NElts; ++i) {
APSInt Tmp = Init.extOrTrunc(EltWidth);
@@ -862,7 +898,7 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
unsigned NumElements = VT->getNumElements();
QualType EltTy = VT->getElementType();
- llvm::SmallVector<APValue, 4> Elements;
+ SmallVector<APValue, 4> Elements;
// If a vector is initialized with a single element, that value
// becomes every element of the vector, not just the first.
@@ -926,7 +962,7 @@ VectorExprEvaluator::GetZeroVector(QualType T) {
ZeroElement =
APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)));
- llvm::SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement);
+ SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement);
return APValue(&Elements[0], Elements.size());
}
@@ -999,6 +1035,8 @@ public:
return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
}
+ bool ValueInitialization(const Expr *E) { return Success(0, E); }
+
//===--------------------------------------------------------------------===//
// Visitor Methods
//===--------------------------------------------------------------------===//
@@ -1039,16 +1077,9 @@ public:
return Success(E->getValue(), E);
}
+ // Note, GNU defines __null as an integer, not a pointer.
bool VisitGNUNullExpr(const GNUNullExpr *E) {
- return Success(0, E);
- }
-
- bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
- return Success(0, E);
- }
-
- bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
- return Success(0, E);
+ return ValueInitialization(E);
}
bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
@@ -1072,7 +1103,7 @@ public:
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
-
+
private:
CharUnits GetAlignOfExpr(const Expr *E);
CharUnits GetAlignOfType(QualType T);
@@ -1210,7 +1241,7 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E) {
else if (ArgTy->isUnionType())
return union_type_class;
else // FIXME: offset_type_class, method_type_class, & lang_type_class?
- assert(0 && "CallExpr::isBuiltinClassifyType(): unimplemented type");
+ llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
return -1;
}
@@ -1267,7 +1298,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
// If evaluating the argument has side-effects we can't determine
// the size of the object and lower it to unknown now.
if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
- if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1)
+ if (E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue() <= 1)
return Success(-1ULL, E);
return Success(0, E);
}
@@ -1284,8 +1315,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(E->getArg(0)->isEvaluatable(Info.Ctx), E);
case Builtin::BI__builtin_eh_return_data_regno: {
- int Operand = E->getArg(0)->EvaluateAsInt(Info.Ctx).getZExtValue();
- Operand = Info.Ctx.Target.getEHDataRegisterNumber(Operand);
+ int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue();
+ Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand);
return Success(Operand, E);
}
@@ -1300,9 +1331,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
= dyn_cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts())) {
// The string literal may have embedded null characters. Find the first
// one and truncate there.
- llvm::StringRef Str = S->getString();
- llvm::StringRef::size_type Pos = Str.find(0);
- if (Pos != llvm::StringRef::npos)
+ StringRef Str = S->getString();
+ StringRef::size_type Pos = Str.find(0);
+ if (Pos != StringRef::npos)
Str = Str.substr(0, Pos);
return Success(Str.size(), E);
@@ -1419,7 +1450,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default:
- assert(0 && "Invalid binary operator!");
+ llvm_unreachable("Invalid binary operator!");
case BO_LT:
return Success(CR == APFloat::cmpLessThan, E);
case BO_GT:
@@ -1801,7 +1832,8 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_VectorSplat:
case CK_IntegralToFloating:
case CK_FloatingCast:
- case CK_AnyPointerToObjCPointerCast:
+ case CK_CPointerToObjCPointerCast:
+ case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast:
case CK_FloatingRealToComplex:
@@ -1818,9 +1850,10 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_GetObjCProperty:
case CK_LValueBitCast:
case CK_UserDefinedConversion:
- case CK_ObjCProduceObject:
- case CK_ObjCConsumeObject:
- case CK_ObjCReclaimReturnedObject:
+ case CK_ARCProduceObject:
+ case CK_ARCConsumeObject:
+ case CK_ARCReclaimReturnedObject:
+ case CK_ARCExtendBlockObject:
return false;
case CK_LValueToRValue:
@@ -1943,13 +1976,17 @@ public:
return false;
}
+ bool ValueInitialization(const Expr *E) {
+ Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType()));
+ return true;
+ }
+
bool VisitCallExpr(const CallExpr *E);
bool VisitUnaryOperator(const UnaryOperator *E);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitFloatingLiteral(const FloatingLiteral *E);
bool VisitCastExpr(const CastExpr *E);
- bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E);
bool VisitUnaryReal(const UnaryOperator *E);
bool VisitUnaryImag(const UnaryOperator *E);
@@ -2219,11 +2256,6 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) {
return false;
}
-bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
- Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType()));
- return true;
-}
-
//===----------------------------------------------------------------------===//
// Complex Evaluation (for float and integer)
//===----------------------------------------------------------------------===//
@@ -2255,7 +2287,7 @@ public:
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitUnaryOperator(const UnaryOperator *E);
- // FIXME Missing: ImplicitValueInitExpr
+ // FIXME Missing: ImplicitValueInitExpr, InitListExpr
};
} // end anonymous namespace
@@ -2318,16 +2350,18 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_FloatingToIntegral:
case CK_FloatingToBoolean:
case CK_FloatingCast:
- case CK_AnyPointerToObjCPointerCast:
+ case CK_CPointerToObjCPointerCast:
+ case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast:
case CK_FloatingComplexToReal:
case CK_FloatingComplexToBoolean:
case CK_IntegralComplexToReal:
case CK_IntegralComplexToBoolean:
- case CK_ObjCProduceObject:
- case CK_ObjCConsumeObject:
- case CK_ObjCReclaimReturnedObject:
+ case CK_ARCProduceObject:
+ case CK_ARCConsumeObject:
+ case CK_ARCReclaimReturnedObject:
+ case CK_ARCExtendBlockObject:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
@@ -2633,6 +2667,13 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result,
return HandleConversionToBool(this, Result, Info);
}
+bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const {
+ EvalResult Scratch;
+ EvalInfo Info(Ctx, Scratch);
+
+ return EvaluateInteger(this, Result, Info) && !Scratch.HasSideEffects;
+}
+
bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const {
EvalInfo Info(Ctx, Result);
@@ -2671,7 +2712,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
return HasSideEffect(Info).Visit(this);
}
-APSInt Expr::EvaluateAsInt(const ASTContext &Ctx) const {
+APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const {
EvalResult EvalResult;
bool Result = Evaluate(EvalResult, Ctx);
(void)Result;
@@ -2755,7 +2796,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CompoundAssignOperatorClass:
case Expr::CompoundLiteralExprClass:
case Expr::ExtVectorElementExprClass:
- case Expr::InitListExprClass:
case Expr::DesignatedInitExprClass:
case Expr::ImplicitValueInitExprClass:
case Expr::ParenListExprClass:
@@ -2800,6 +2840,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::AsTypeExprClass:
case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::MaterializeTemporaryExprClass:
+ case Expr::AtomicExprClass:
+ return ICEDiag(2, E->getLocStart());
+
+ case Expr::InitListExprClass:
+ if (Ctx.getLangOptions().CPlusPlus0x) {
+ const InitListExpr *ILE = cast<InitListExpr>(E);
+ if (ILE->getNumInits() == 0)
+ return NoDiag();
+ if (ILE->getNumInits() == 1)
+ return CheckICE(ILE->getInit(0), Ctx);
+ // Fall through for more than 1 expression.
+ }
return ICEDiag(2, E->getLocStart());
case Expr::SizeOfPackExprClass:
@@ -2963,11 +3015,11 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// Evaluate gives an error for undefined Div/Rem, so make sure
// we don't evaluate one.
if (LHSResult.Val == 0 && RHSResult.Val == 0) {
- llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx);
+ llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx);
if (REval == 0)
return ICEDiag(1, E->getLocStart());
if (REval.isSigned() && REval.isAllOnesValue()) {
- llvm::APSInt LEval = Exp->getLHS()->EvaluateAsInt(Ctx);
+ llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx);
if (LEval.isMinSignedValue())
return ICEDiag(1, E->getLocStart());
}
@@ -2998,11 +3050,11 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// evaluated are not considered.
if (Ctx.getLangOptions().CPlusPlus0x && LHSResult.Val == 0) {
if (Exp->getOpcode() == BO_LAnd &&
- Exp->getLHS()->EvaluateAsInt(Ctx) == 0)
+ Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)
return LHSResult;
if (Exp->getOpcode() == BO_LOr &&
- Exp->getLHS()->EvaluateAsInt(Ctx) != 0)
+ Exp->getLHS()->EvaluateKnownConstInt(Ctx) != 0)
return LHSResult;
}
@@ -3012,7 +3064,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// to actually check the condition to see whether the side
// with the comma is evaluated.
if ((Exp->getOpcode() == BO_LAnd) !=
- (Exp->getLHS()->EvaluateAsInt(Ctx) == 0))
+ (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0))
return RHSResult;
return NoDiag();
}
@@ -3031,11 +3083,17 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXConstCastExprClass:
case Expr::ObjCBridgedCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
- if (SubExpr->getType()->isIntegralOrEnumerationType())
+ switch (cast<CastExpr>(E)->getCastKind()) {
+ case CK_LValueToRValue:
+ case CK_NoOp:
+ case CK_IntegralToBoolean:
+ case CK_IntegralCast:
return CheckICE(SubExpr, Ctx);
- if (isa<FloatingLiteral>(SubExpr->IgnoreParens()))
- return NoDiag();
- return ICEDiag(2, E->getLocStart());
+ default:
+ if (isa<FloatingLiteral>(SubExpr->IgnoreParens()))
+ return NoDiag();
+ return ICEDiag(2, E->getLocStart());
+ }
}
case Expr::BinaryConditionalOperatorClass: {
const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E);
@@ -3045,7 +3103,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
if (FalseResult.Val == 2) return FalseResult;
if (CommonResult.Val == 1) return CommonResult;
if (FalseResult.Val == 1 &&
- Exp->getCommon()->EvaluateAsInt(Ctx) == 0) return NoDiag();
+ Exp->getCommon()->EvaluateKnownConstInt(Ctx) == 0) return NoDiag();
return FalseResult;
}
case Expr::ConditionalOperatorClass: {
@@ -3072,7 +3130,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// subexpressions of [...] conditional (5.16) operations that
// are not evaluated are not considered
bool TrueBranch = Ctx.getLangOptions().CPlusPlus0x
- ? Exp->getCond()->EvaluateAsInt(Ctx) != 0
+ ? Exp->getCond()->EvaluateKnownConstInt(Ctx) != 0
: false;
ICEDiag TrueResult = NoDiag();
if (!Ctx.getLangOptions().CPlusPlus0x || TrueBranch)
@@ -3092,7 +3150,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// Rare case where the diagnostics depend on which side is evaluated
// Note that if we get here, CondResult is 0, and at least one of
// TrueResult and FalseResult is non-zero.
- if (Exp->getCond()->EvaluateAsInt(Ctx) == 0) {
+ if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) {
return FalseResult;
}
return TrueResult;
diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp
index b96d65a729ca..fd616dbc9d2f 100644
--- a/lib/AST/ExternalASTSource.cpp
+++ b/lib/AST/ExternalASTSource.cpp
@@ -49,12 +49,10 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
return DeclContext::lookup_result();
}
-void ExternalASTSource::MaterializeVisibleDecls(const DeclContext *DC) { }
-
ExternalLoadResult
ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
- llvm::SmallVectorImpl<Decl*> &Result) {
+ SmallVectorImpl<Decl*> &Result) {
return ELR_AlreadyLoaded;
}
diff --git a/lib/AST/InheritViz.cpp b/lib/AST/InheritViz.cpp
index c47a9dadbadd..b70520f44dc5 100644
--- a/lib/AST/InheritViz.cpp
+++ b/lib/AST/InheritViz.cpp
@@ -33,12 +33,12 @@ namespace clang {
/// vs. non-virtual bases.
class InheritanceHierarchyWriter {
ASTContext& Context;
- llvm::raw_ostream &Out;
+ raw_ostream &Out;
std::map<QualType, int, QualTypeOrdering> DirectBaseCount;
std::set<QualType, QualTypeOrdering> KnownVirtualBases;
public:
- InheritanceHierarchyWriter(ASTContext& Context, llvm::raw_ostream& Out)
+ InheritanceHierarchyWriter(ASTContext& Context, raw_ostream& Out)
: Context(Context), Out(Out) { }
void WriteGraph(QualType Type) {
@@ -55,7 +55,7 @@ protected:
/// WriteNodeReference - Write out a reference to the given node,
/// using a unique identifier for each direct base and for the
/// (only) virtual base.
- llvm::raw_ostream& WriteNodeReference(QualType Type, bool FromVirtual);
+ raw_ostream& WriteNodeReference(QualType Type, bool FromVirtual);
};
void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
@@ -120,7 +120,7 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
/// WriteNodeReference - Write out a reference to the given node,
/// using a unique identifier for each direct base and for the
/// (only) virtual base.
-llvm::raw_ostream&
+raw_ostream&
InheritanceHierarchyWriter::WriteNodeReference(QualType Type,
bool FromVirtual) {
QualType CanonType = Context.getCanonicalType(Type);
diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp
index 30aece3ee73b..0027dbf1915b 100644
--- a/lib/AST/ItaniumCXXABI.cpp
+++ b/lib/AST/ItaniumCXXABI.cpp
@@ -53,7 +53,7 @@ public:
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
CharUnits PointerSize =
- Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0));
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
return Layout.getNonVirtualSize() == PointerSize;
}
};
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index ec9863b298e6..acedf70f29c5 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -73,7 +73,7 @@ class ItaniumMangleContext : public MangleContext {
public:
explicit ItaniumMangleContext(ASTContext &Context,
- Diagnostic &Diags)
+ DiagnosticsEngine &Diags)
: MangleContext(Context, Diags) { }
uint64_t getAnonymousStructId(const TagDecl *TD) {
@@ -92,30 +92,30 @@ public:
/// @{
bool shouldMangleDeclName(const NamedDecl *D);
- void mangleName(const NamedDecl *D, llvm::raw_ostream &);
+ void mangleName(const NamedDecl *D, raw_ostream &);
void mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
- llvm::raw_ostream &);
+ raw_ostream &);
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
- llvm::raw_ostream &);
+ raw_ostream &);
void mangleReferenceTemporary(const VarDecl *D,
- llvm::raw_ostream &);
+ raw_ostream &);
void mangleCXXVTable(const CXXRecordDecl *RD,
- llvm::raw_ostream &);
+ raw_ostream &);
void mangleCXXVTT(const CXXRecordDecl *RD,
- llvm::raw_ostream &);
+ raw_ostream &);
void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
const CXXRecordDecl *Type,
- llvm::raw_ostream &);
- void mangleCXXRTTI(QualType T, llvm::raw_ostream &);
- void mangleCXXRTTIName(QualType T, llvm::raw_ostream &);
+ raw_ostream &);
+ void mangleCXXRTTI(QualType T, raw_ostream &);
+ void mangleCXXRTTIName(QualType T, raw_ostream &);
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
- llvm::raw_ostream &);
+ raw_ostream &);
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
- llvm::raw_ostream &);
+ raw_ostream &);
- void mangleItaniumGuardVariable(const VarDecl *D, llvm::raw_ostream &);
+ void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &);
void mangleInitDiscriminator() {
Discriminator = 0;
@@ -136,7 +136,7 @@ public:
/// CXXNameMangler - Manage the mangling of a single name.
class CXXNameMangler {
ItaniumMangleContext &Context;
- llvm::raw_ostream &Out;
+ raw_ostream &Out;
/// The "structor" is the top-level declaration being mangled, if
/// that's not a template specialization; otherwise it's the pattern
@@ -191,7 +191,7 @@ class CXXNameMangler {
ASTContext &getASTContext() const { return Context.getASTContext(); }
public:
- CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_,
+ CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
const NamedDecl *D = 0)
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0),
SeqID(0) {
@@ -199,11 +199,11 @@ public:
assert(!D || (!isa<CXXDestructorDecl>(D) &&
!isa<CXXConstructorDecl>(D)));
}
- CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_,
+ CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
const CXXConstructorDecl *D, CXXCtorType Type)
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
SeqID(0) { }
- CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_,
+ CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
const CXXDestructorDecl *D, CXXDtorType Type)
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
SeqID(0) { }
@@ -219,9 +219,9 @@ public:
free(result);
}
#endif
- llvm::raw_ostream &getStream() { return Out; }
+ raw_ostream &getStream() { return Out; }
- void mangle(const NamedDecl *D, llvm::StringRef Prefix = "_Z");
+ void mangle(const NamedDecl *D, StringRef Prefix = "_Z");
void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
void mangleNumber(const llvm::APSInt &I);
void mangleNumber(int64_t Number);
@@ -310,7 +310,7 @@ private:
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
- void mangleTemplateArgs(const ExplicitTemplateArgumentList &TemplateArgs);
+ void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);
void mangleTemplateArgs(TemplateName Template,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
@@ -385,7 +385,7 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) {
return true;
}
-void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) {
+void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
// Any decl can be declared with __asm("foo") on it, and this takes precedence
// over all other naming in the .o file.
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
@@ -397,8 +397,8 @@ void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) {
// llvm mangler on ELF is a nop, so we can just avoid adding the \01
// marker. We also avoid adding the marker if this is an alias for an
// LLVM intrinsic.
- llvm::StringRef UserLabelPrefix =
- getASTContext().Target.getUserLabelPrefix();
+ StringRef UserLabelPrefix =
+ getASTContext().getTargetInfo().getUserLabelPrefix();
if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm."))
Out << '\01'; // LLVM IR Marker for __asm("foo")
@@ -788,6 +788,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::Atomic:
llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstTemplateTypeParmPack:
@@ -1069,8 +1070,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- assert(false && "Can't mangle Objective-C selector names here!");
- break;
+ llvm_unreachable("Can't mangle Objective-C selector names here!");
case DeclarationName::CXXConstructorName:
if (ND == Structor)
@@ -1124,8 +1124,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
break;
case DeclarationName::CXXUsingDirective:
- assert(false && "Can't mangle a using directive name!");
- break;
+ llvm_unreachable("Can't mangle a using directive name!");
}
}
@@ -1512,8 +1511,7 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
case OO_None:
case NUM_OVERLOADED_OPERATORS:
- assert(false && "Not an overloaded operator");
- break;
+ llvm_unreachable("Not an overloaded operator");
}
}
@@ -1538,7 +1536,7 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
Out << 'U' << ASString.size() << ASString;
}
- llvm::StringRef LifetimeName;
+ StringRef LifetimeName;
switch (Quals.getObjCLifetime()) {
// Objective-C ARC Extension:
//
@@ -1706,7 +1704,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
// UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
// UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
// UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
- // UNSUPPORTED: ::= Dh # IEEE 754r half-precision floating point (16 bits)
+ // ::= Dh # IEEE 754r half-precision floating point (16 bits)
// ::= Di # char32_t
// ::= Ds # char16_t
// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
@@ -1731,6 +1729,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::Long: Out << 'l'; break;
case BuiltinType::LongLong: Out << 'x'; break;
case BuiltinType::Int128: Out << 'n'; break;
+ case BuiltinType::Half: Out << "Dh"; break;
case BuiltinType::Float: Out << 'f'; break;
case BuiltinType::Double: Out << 'd'; break;
case BuiltinType::LongDouble: Out << 'e'; break;
@@ -2114,6 +2113,13 @@ void CXXNameMangler::mangleType(const AutoType *T) {
mangleType(D);
}
+void CXXNameMangler::mangleType(const AtomicType *T) {
+ // <type> ::= U <source-name> <type> # vendor extended type qualifier
+ // (Until there's a standardized mangling...)
+ Out << "U7_Atomic";
+ mangleType(T->getValueType());
+}
+
void CXXNameMangler::mangleIntegerLiteral(QualType T,
const llvm::APSInt &Value) {
// <expr-primary> ::= L <type> <value number> E # integer literal
@@ -2250,10 +2256,11 @@ recurse:
case Expr::CXXNoexceptExprClass:
case Expr::CUDAKernelCallExprClass:
case Expr::AsTypeExprClass:
+ case Expr::AtomicExprClass:
{
// As bad as this diagnostic is, it's better than crashing.
- Diagnostic &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot yet mangle expression type %0");
Diags.Report(E->getExprLoc(), DiagID)
<< E->getStmtClassName() << E->getSourceRange();
@@ -2262,9 +2269,9 @@ recurse:
// Even gcc-4.5 doesn't mangle this.
case Expr::BinaryConditionalOperatorClass: {
- Diagnostic &Diags = Context.getDiags();
+ DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID =
- Diags.getCustomDiagID(Diagnostic::Error,
+ Diags.getCustomDiagID(DiagnosticsEngine::Error,
"?: operator with omitted middle operand cannot be mangled");
Diags.Report(E->getExprLoc(), DiagID)
<< E->getStmtClassName() << E->getSourceRange();
@@ -2411,7 +2418,8 @@ recurse:
QualType T = (ImplicitlyConvertedToType.isNull() ||
!ImplicitlyConvertedToType->isIntegerType())? SAE->getType()
: ImplicitlyConvertedToType;
- mangleIntegerLiteral(T, SAE->EvaluateAsInt(Context.getASTContext()));
+ llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext());
+ mangleIntegerLiteral(T, V);
break;
}
@@ -2423,8 +2431,8 @@ recurse:
Out << 'a';
break;
case UETT_VecStep:
- Diagnostic &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot yet mangle vec_step expression");
Diags.Report(DiagID);
return;
@@ -2526,7 +2534,7 @@ recurse:
case Expr::ObjCBridgedCastExprClass: {
// Mangle ownership casts as a vendor extended operator __bridge,
// __bridge_transfer, or __bridge_retain.
- llvm::StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
+ StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
Out << "v1U" << Kind.size() << Kind;
}
// Fall through to mangle the cast itself.
@@ -2817,7 +2825,7 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
}
void CXXNameMangler::mangleTemplateArgs(
- const ExplicitTemplateArgumentList &TemplateArgs) {
+ const ASTTemplateArgumentListInfo &TemplateArgs) {
// <template-args> ::= I <template-arg>+ E
Out << 'I';
for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)
@@ -3021,7 +3029,7 @@ bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
}
Out << 'S'
- << llvm::StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr)
+ << StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr)
<< '_';
}
@@ -3196,7 +3204,7 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
/// emit the identifier of the declaration (\c D->getIdentifier()) as its
/// name.
void ItaniumMangleContext::mangleName(const NamedDecl *D,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
"Invalid mangleName() call, argument is not a variable or function!");
assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
@@ -3212,21 +3220,21 @@ void ItaniumMangleContext::mangleName(const NamedDecl *D,
void ItaniumMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
CXXCtorType Type,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
CXXNameMangler Mangler(*this, Out, D, Type);
Mangler.mangle(D);
}
void ItaniumMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
CXXDtorType Type,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
CXXNameMangler Mangler(*this, Out, D, Type);
Mangler.mangle(D);
}
void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// <special-name> ::= T <call-offset> <base encoding>
// # base is the nominal target function of thunk
// <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
@@ -3256,7 +3264,7 @@ void
ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// <special-name> ::= T <call-offset> <base encoding>
// # base is the nominal target function of thunk
CXXNameMangler Mangler(*this, Out, DD, Type);
@@ -3272,7 +3280,7 @@ ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
/// mangleGuardVariable - Returns the mangled name for a guard variable
/// for the passed in VarDecl.
void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// <special-name> ::= GV <object name> # Guard variable for one-time
// # initialization
CXXNameMangler Mangler(*this, Out);
@@ -3281,7 +3289,7 @@ void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D,
}
void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// We match the GCC mangling here.
// <special-name> ::= GR <object name>
CXXNameMangler Mangler(*this, Out);
@@ -3290,7 +3298,7 @@ void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D,
}
void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// <special-name> ::= TV <type> # virtual table
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZTV";
@@ -3298,7 +3306,7 @@ void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
}
void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// <special-name> ::= TT <type> # VTT structure
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZTT";
@@ -3308,7 +3316,7 @@ void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
int64_t Offset,
const CXXRecordDecl *Type,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// <special-name> ::= TC <type> <offset number> _ <base type>
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZTC";
@@ -3319,7 +3327,7 @@ void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
}
void ItaniumMangleContext::mangleCXXRTTI(QualType Ty,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// <special-name> ::= TI <type> # typeinfo structure
assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers");
CXXNameMangler Mangler(*this, Out);
@@ -3328,7 +3336,7 @@ void ItaniumMangleContext::mangleCXXRTTI(QualType Ty,
}
void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
// <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZTS";
@@ -3336,6 +3344,6 @@ void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty,
}
MangleContext *clang::createItaniumMangleContext(ASTContext &Context,
- Diagnostic &Diags) {
+ DiagnosticsEngine &Diags) {
return new ItaniumMangleContext(Context, Diags);
}
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index c3f3b11caccf..5cb8f47519ec 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -37,9 +37,9 @@ using namespace clang;
namespace {
static void mangleFunctionBlock(MangleContext &Context,
- llvm::StringRef Outer,
+ StringRef Outer,
const BlockDecl *BD,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
Out << "__" << Outer << "_block_invoke_" << Context.getBlockId(BD, true);
}
@@ -60,13 +60,13 @@ static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) {
}
void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
Out << "__block_global_" << getBlockId(BD, false);
}
void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
CXXCtorType CT, const BlockDecl *BD,
- llvm::raw_ostream &ResStream) {
+ raw_ostream &ResStream) {
checkMangleDC(CD, BD);
llvm::SmallString<64> Buffer;
llvm::raw_svector_ostream Out(Buffer);
@@ -77,7 +77,7 @@ void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
CXXDtorType DT, const BlockDecl *BD,
- llvm::raw_ostream &ResStream) {
+ raw_ostream &ResStream) {
checkMangleDC(DD, BD);
llvm::SmallString<64> Buffer;
llvm::raw_svector_ostream Out(Buffer);
@@ -87,7 +87,7 @@ void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
}
void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
checkMangleDC(DC, BD);
@@ -113,7 +113,7 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
}
void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
llvm::SmallString<64> Name;
llvm::raw_svector_ostream OS(Name);
@@ -129,7 +129,7 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
}
void MangleContext::mangleBlock(const BlockDecl *BD,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
const DeclContext *DC = BD->getDeclContext();
while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC))
DC = DC->getParent();
diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp
index 206f6dd0c9eb..f33d6fe1f563 100644
--- a/lib/AST/MicrosoftCXXABI.cpp
+++ b/lib/AST/MicrosoftCXXABI.cpp
@@ -30,7 +30,7 @@ public:
unsigned getMemberPointerSize(const MemberPointerType *MPT) const;
CallingConv getDefaultMethodCallConv() const {
- if (Context.Target.getTriple().getArch() == llvm::Triple::x86)
+ if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
return CC_X86ThisCall;
else
return CC_C;
@@ -45,7 +45,7 @@ public:
// In the Microsoft ABI, classes can have one or two vtable pointers.
CharUnits PointerSize =
- Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0));
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
return Layout.getNonVirtualSize() == PointerSize ||
Layout.getNonVirtualSize() == PointerSize * 2;
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 4f920f9aaca7..1515db49fe3c 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -29,15 +29,15 @@ namespace {
/// Microsoft Visual C++ ABI.
class MicrosoftCXXNameMangler {
MangleContext &Context;
- llvm::raw_ostream &Out;
+ raw_ostream &Out;
ASTContext &getASTContext() const { return Context.getASTContext(); }
public:
- MicrosoftCXXNameMangler(MangleContext &C, llvm::raw_ostream &Out_)
+ MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
: Context(C), Out(Out_) { }
- void mangle(const NamedDecl *D, llvm::StringRef Prefix = "?");
+ void mangle(const NamedDecl *D, StringRef Prefix = "?");
void mangleName(const NamedDecl *ND);
void mangleFunctionEncoding(const FunctionDecl *FD);
void mangleVariableEncoding(const VarDecl *VD);
@@ -78,30 +78,30 @@ private:
class MicrosoftMangleContext : public MangleContext {
public:
MicrosoftMangleContext(ASTContext &Context,
- Diagnostic &Diags) : MangleContext(Context, Diags) { }
+ DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }
virtual bool shouldMangleDeclName(const NamedDecl *D);
- virtual void mangleName(const NamedDecl *D, llvm::raw_ostream &Out);
+ virtual void mangleName(const NamedDecl *D, raw_ostream &Out);
virtual void mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
- llvm::raw_ostream &);
+ raw_ostream &);
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
- llvm::raw_ostream &);
+ raw_ostream &);
virtual void mangleCXXVTable(const CXXRecordDecl *RD,
- llvm::raw_ostream &);
+ raw_ostream &);
virtual void mangleCXXVTT(const CXXRecordDecl *RD,
- llvm::raw_ostream &);
+ raw_ostream &);
virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
const CXXRecordDecl *Type,
- llvm::raw_ostream &);
- virtual void mangleCXXRTTI(QualType T, llvm::raw_ostream &);
- virtual void mangleCXXRTTIName(QualType T, llvm::raw_ostream &);
+ raw_ostream &);
+ virtual void mangleCXXRTTI(QualType T, raw_ostream &);
+ virtual void mangleCXXRTTIName(QualType T, raw_ostream &);
virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
- llvm::raw_ostream &);
+ raw_ostream &);
virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
- llvm::raw_ostream &);
+ raw_ostream &);
virtual void mangleReferenceTemporary(const clang::VarDecl *,
- llvm::raw_ostream &);
+ raw_ostream &);
};
}
@@ -154,7 +154,7 @@ bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {
}
void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
- llvm::StringRef Prefix) {
+ StringRef Prefix) {
// MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
// Therefore it's really important that we don't decorate the
// name with leading underscores or leading/trailing at signs. So, emit a
@@ -332,16 +332,13 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- assert(false && "Can't mangle Objective-C selector names here!");
- break;
+ llvm_unreachable("Can't mangle Objective-C selector names here!");
case DeclarationName::CXXConstructorName:
- assert(false && "Can't mangle constructors yet!");
- break;
+ llvm_unreachable("Can't mangle constructors yet!");
case DeclarationName::CXXDestructorName:
- assert(false && "Can't mangle destructors yet!");
- break;
+ llvm_unreachable("Can't mangle destructors yet!");
case DeclarationName::CXXConversionFunctionName:
// <operator-name> ::= ?B # (cast)
@@ -355,12 +352,10 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
case DeclarationName::CXXLiteralOperatorName:
// FIXME: Was this added in VS2010? Does MS even know how to mangle this?
- assert(false && "Don't know how to mangle literal operators yet!");
- break;
+ llvm_unreachable("Don't know how to mangle literal operators yet!");
case DeclarationName::CXXUsingDirective:
- assert(false && "Can't mangle a using directive name!");
- break;
+ llvm_unreachable("Can't mangle a using directive name!");
}
}
@@ -513,13 +508,11 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO) {
case OO_Array_Delete: Out << "?_V"; break;
case OO_Conditional:
- assert(false && "Don't know how to mangle ?:");
- break;
+ llvm_unreachable("Don't know how to mangle ?:");
case OO_None:
case NUM_OVERLOADED_OPERATORS:
- assert(false && "Not an overloaded operator");
- break;
+ llvm_unreachable("Not an overloaded operator");
}
}
@@ -712,18 +705,17 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::Dependent:
case BuiltinType::UnknownAny:
case BuiltinType::BoundMember:
- assert(false &&
+ llvm_unreachable(
"Overloaded and dependent types shouldn't get to name mangling");
- break;
case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break;
case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break;
case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break;
case BuiltinType::Char16:
case BuiltinType::Char32:
+ case BuiltinType::Half:
case BuiltinType::NullPtr:
- assert(false && "Don't know how to mangle this type");
- break;
+ llvm_unreachable("Don't know how to mangle this type");
}
}
@@ -869,7 +861,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
CC = IsInstMethod ? getASTContext().getDefaultMethodCallConv() : CC_C;
switch (CC) {
default:
- assert(0 && "Unsupported CC for mangling");
+ llvm_unreachable("Unsupported CC for mangling");
case CC_Default:
case CC_C: Out << 'A'; break;
case CC_X86Pascal: Out << 'C'; break;
@@ -890,7 +882,7 @@ void MicrosoftCXXNameMangler::mangleThrowSpecification(
}
void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T) {
- assert(false && "Don't know how to mangle UnresolvedUsingTypes yet!");
+ llvm_unreachable("Don't know how to mangle UnresolvedUsingTypes yet!");
}
// <type> ::= <union-type> | <struct-type> | <class-type> | <enum-type>
@@ -954,7 +946,7 @@ void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T) {
mangleType(static_cast<const ArrayType *>(T), false);
}
void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
- llvm::SmallVector<llvm::APInt, 3> Dimensions;
+ SmallVector<llvm::APInt, 3> Dimensions;
for (;;) {
if (ElementTy->isConstantArrayType()) {
const ConstantArrayType *CAT =
@@ -962,10 +954,10 @@ void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
Dimensions.push_back(CAT->getSize());
ElementTy = CAT->getElementType();
} else if (ElementTy->isVariableArrayType()) {
- assert(false && "Don't know how to mangle VLAs!");
+ llvm_unreachable("Don't know how to mangle VLAs!");
} else if (ElementTy->isDependentSizedArrayType()) {
// The dependent expression has to be folded into a constant (TODO).
- assert(false && "Don't know how to mangle dependent-sized arrays!");
+ llvm_unreachable("Don't know how to mangle dependent-sized arrays!");
} else if (ElementTy->isIncompleteArrayType()) continue;
else break;
}
@@ -999,12 +991,12 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T) {
}
void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T) {
- assert(false && "Don't know how to mangle TemplateTypeParmTypes yet!");
+ llvm_unreachable("Don't know how to mangle TemplateTypeParmTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(
const SubstTemplateTypeParmPackType *T) {
- assert(false &&
+ llvm_unreachable(
"Don't know how to mangle SubstTemplateTypeParmPackTypes yet!");
}
@@ -1045,21 +1037,22 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T) {
}
void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T) {
- assert(false && "Don't know how to mangle RValueReferenceTypes yet!");
+ llvm_unreachable("Don't know how to mangle RValueReferenceTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const ComplexType *T) {
- assert(false && "Don't know how to mangle ComplexTypes yet!");
+ llvm_unreachable("Don't know how to mangle ComplexTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const VectorType *T) {
- assert(false && "Don't know how to mangle VectorTypes yet!");
+ llvm_unreachable("Don't know how to mangle VectorTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T) {
- assert(false && "Don't know how to mangle ExtVectorTypes yet!");
+ llvm_unreachable("Don't know how to mangle ExtVectorTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
- assert(false && "Don't know how to mangle DependentSizedExtVectorTypes yet!");
+ llvm_unreachable(
+ "Don't know how to mangle DependentSizedExtVectorTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T) {
@@ -1080,49 +1073,53 @@ void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T) {
}
void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T) {
- assert(false && "Don't know how to mangle InjectedClassNameTypes yet!");
+ llvm_unreachable("Don't know how to mangle InjectedClassNameTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T) {
- assert(false && "Don't know how to mangle TemplateSpecializationTypes yet!");
+ llvm_unreachable("Don't know how to mangle TemplateSpecializationTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T) {
- assert(false && "Don't know how to mangle DependentNameTypes yet!");
+ llvm_unreachable("Don't know how to mangle DependentNameTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(
const DependentTemplateSpecializationType *T) {
- assert(false &&
+ llvm_unreachable(
"Don't know how to mangle DependentTemplateSpecializationTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T) {
- assert(false && "Don't know how to mangle PackExpansionTypes yet!");
+ llvm_unreachable("Don't know how to mangle PackExpansionTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T) {
- assert(false && "Don't know how to mangle TypeOfTypes yet!");
+ llvm_unreachable("Don't know how to mangle TypeOfTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T) {
- assert(false && "Don't know how to mangle TypeOfExprTypes yet!");
+ llvm_unreachable("Don't know how to mangle TypeOfExprTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T) {
- assert(false && "Don't know how to mangle DecltypeTypes yet!");
+ llvm_unreachable("Don't know how to mangle DecltypeTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T) {
- assert(false && "Don't know how to mangle UnaryTransformationTypes yet!");
+ llvm_unreachable("Don't know how to mangle UnaryTransformationTypes yet!");
}
void MicrosoftCXXNameMangler::mangleType(const AutoType *T) {
- assert(false && "Don't know how to mangle AutoTypes yet!");
+ llvm_unreachable("Don't know how to mangle AutoTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const AtomicType *T) {
+ llvm_unreachable("Don't know how to mangle AtomicTypes yet!");
}
void MicrosoftMangleContext::mangleName(const NamedDecl *D,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
"Invalid mangleName() call, argument is not a variable or function!");
assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
@@ -1137,53 +1134,53 @@ void MicrosoftMangleContext::mangleName(const NamedDecl *D,
}
void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
- llvm::raw_ostream &) {
- assert(false && "Can't yet mangle thunks!");
+ raw_ostream &) {
+ llvm_unreachable("Can't yet mangle thunks!");
}
void MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
CXXDtorType Type,
const ThisAdjustment &,
- llvm::raw_ostream &) {
- assert(false && "Can't yet mangle destructor thunks!");
+ raw_ostream &) {
+ llvm_unreachable("Can't yet mangle destructor thunks!");
}
void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
- llvm::raw_ostream &) {
- assert(false && "Can't yet mangle virtual tables!");
+ raw_ostream &) {
+ llvm_unreachable("Can't yet mangle virtual tables!");
}
void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
- llvm::raw_ostream &) {
+ raw_ostream &) {
llvm_unreachable("The MS C++ ABI does not have virtual table tables!");
}
void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
int64_t Offset,
const CXXRecordDecl *Type,
- llvm::raw_ostream &) {
+ raw_ostream &) {
llvm_unreachable("The MS C++ ABI does not have constructor vtables!");
}
void MicrosoftMangleContext::mangleCXXRTTI(QualType T,
- llvm::raw_ostream &) {
- assert(false && "Can't yet mangle RTTI!");
+ raw_ostream &) {
+ llvm_unreachable("Can't yet mangle RTTI!");
}
void MicrosoftMangleContext::mangleCXXRTTIName(QualType T,
- llvm::raw_ostream &) {
- assert(false && "Can't yet mangle RTTI names!");
+ raw_ostream &) {
+ llvm_unreachable("Can't yet mangle RTTI names!");
}
void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
CXXCtorType Type,
- llvm::raw_ostream &) {
- assert(false && "Can't yet mangle constructors!");
+ raw_ostream &) {
+ llvm_unreachable("Can't yet mangle constructors!");
}
void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
CXXDtorType Type,
- llvm::raw_ostream &) {
- assert(false && "Can't yet mangle destructors!");
+ raw_ostream &) {
+ llvm_unreachable("Can't yet mangle destructors!");
}
void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *,
- llvm::raw_ostream &) {
- assert(false && "Can't yet mangle reference temporaries!");
+ raw_ostream &) {
+ llvm_unreachable("Can't yet mangle reference temporaries!");
}
MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,
- Diagnostic &Diags) {
+ DiagnosticsEngine &Diags) {
return new MicrosoftMangleContext(Context, Diags);
}
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index f6d4f2513ce4..1ff2e7177b3b 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -218,7 +218,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
/// \brief Print this nested name specifier to the given output
/// stream.
void
-NestedNameSpecifier::print(llvm::raw_ostream &OS,
+NestedNameSpecifier::print(raw_ostream &OS,
const PrintingPolicy &Policy) const {
if (getPrefix())
getPrefix()->print(OS, Policy);
@@ -569,7 +569,7 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
// Construct bogus (but well-formed) source information for the
// nested-name-specifier.
BufferSize = 0;
- llvm::SmallVector<NestedNameSpecifier *, 4> Stack;
+ SmallVector<NestedNameSpecifier *, 4> Stack;
for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
Stack.push_back(NNS);
while (!Stack.empty()) {
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index b7b2005e9f84..5eef83a81a8b 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -66,6 +66,14 @@ Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
return S;
}
+Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
+ do {
+ S = getParent(S);
+ } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
+
+ return S;
+}
+
Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
Stmt *Paren = 0;
while (isa<ParenExpr>(S)) {
diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp
index 035c48fd0827..ccc591a28f32 100644
--- a/lib/AST/RecordLayout.cpp
+++ b/lib/AST/RecordLayout.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/TargetInfo.h"
using namespace clang;
@@ -42,7 +43,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
// Constructor for C++ records.
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
- CharUnits datasize,
+ CharUnits vbptroffset, CharUnits datasize,
const uint64_t *fieldoffsets,
unsigned fieldcount,
CharUnits nonvirtualsize,
@@ -67,15 +68,20 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
CXXInfo->BaseOffsets = BaseOffsets;
CXXInfo->VBaseOffsets = VBaseOffsets;
+ CXXInfo->VBPtrOffset = vbptroffset;
#ifndef NDEBUG
if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) {
- if (isPrimaryBaseVirtual())
+ if (isPrimaryBaseVirtual()) {
+ // Microsoft ABI doesn't have primary virtual base
+ if (Ctx.getTargetInfo().getCXXABI() != CXXABI_Microsoft) {
assert(getVBaseClassOffset(PrimaryBase).isZero() &&
"Primary virtual base must be at offset 0!");
- else
+ }
+ } else {
assert(getBaseClassOffsetInBits(PrimaryBase) == 0 &&
"Primary base must be at offset 0!");
+ }
}
#endif
}
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 5636a6f0f64a..bbd3fc016017 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -44,7 +44,7 @@ struct BaseSubobjectInfo {
bool IsVirtual;
/// Bases - Information about the base subobjects.
- llvm::SmallVector<BaseSubobjectInfo*, 4> Bases;
+ SmallVector<BaseSubobjectInfo*, 4> Bases;
/// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base
/// of this base info (if one exists).
@@ -64,7 +64,7 @@ class EmptySubobjectMap {
const CXXRecordDecl *Class;
/// EmptyClassOffsets - A map from offsets to empty record decls.
- typedef llvm::SmallVector<const CXXRecordDecl *, 1> ClassVectorTy;
+ typedef SmallVector<const CXXRecordDecl *, 1> ClassVectorTy;
typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
EmptyClassOffsetsMapTy EmptyClassOffsets;
@@ -556,7 +556,7 @@ protected:
/// \brief The alignment if attribute packed is not used.
CharUnits UnpackedAlignment;
- llvm::SmallVector<uint64_t, 16> FieldOffsets;
+ SmallVector<uint64_t, 16> FieldOffsets;
/// Packed - Whether the record is packed or not.
unsigned Packed : 1;
@@ -592,6 +592,9 @@ protected:
/// out is virtual.
bool PrimaryBaseIsVirtual;
+ /// VBPtrOffset - Virtual base table offset. Only for MS layout.
+ CharUnits VBPtrOffset;
+
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
/// Bases - base classes and their offsets in the record.
@@ -613,16 +616,17 @@ protected:
llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
RecordLayoutBuilder(const ASTContext &Context, EmptySubobjectMap
- *EmptySubobjects)
+ *EmptySubobjects, CharUnits Alignment)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
- Alignment(CharUnits::One()), UnpackedAlignment(Alignment),
+ Alignment(Alignment), UnpackedAlignment(Alignment),
Packed(false), IsUnion(false),
IsMac68kAlign(false), IsMsStruct(false),
UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()),
DataSize(0), NonVirtualSize(CharUnits::Zero()),
NonVirtualAlignment(CharUnits::One()),
ZeroLengthBitfield(0), PrimaryBase(0),
- PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { }
+ PrimaryBaseIsVirtual(false), VBPtrOffset(CharUnits::fromQuantity(-1)),
+ FirstNearlyEmptyVBase(0) { }
void Layout(const RecordDecl *D);
void Layout(const CXXRecordDecl *D);
@@ -633,6 +637,8 @@ protected:
void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize,
bool FieldPacked, const FieldDecl *D);
void LayoutBitField(const FieldDecl *D);
+ void MSLayoutVirtualBases(const CXXRecordDecl *RD);
+ void MSLayout(const CXXRecordDecl *RD);
/// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects.
llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
@@ -663,7 +669,7 @@ protected:
void SelectPrimaryVBase(const CXXRecordDecl *RD);
- virtual CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const;
+ CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const;
/// LayoutNonVirtualBases - Determines the primary base class (if any) and
/// lays it out. Will then proceed to lay out all non-virtual base clasess.
@@ -713,6 +719,8 @@ protected:
void setSize(CharUnits NewSize) { Size = Context.toBits(NewSize); }
void setSize(uint64_t NewSize) { Size = NewSize; }
+ CharUnits getAligment() const { return Alignment; }
+
CharUnits getDataSize() const {
assert(DataSize % Context.getCharWidth() == 0);
return Context.toCharUnitsFromBits(DataSize);
@@ -722,6 +730,11 @@ protected:
void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
+ bool HasVBPtr(const CXXRecordDecl *RD) const;
+ bool HasNewVirtualFunction(const CXXRecordDecl *RD) const;
+
+ /// Add vbptr or vfptr to layout.
+ void AddVPointer();
RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
@@ -729,6 +742,8 @@ public:
static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
virtual ~RecordLayoutBuilder() { }
+
+ CharUnits GetVBPtrOffset() const { return VBPtrOffset; }
};
} // end anonymous namespace
@@ -765,7 +780,7 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
CharUnits
RecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
- return Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0));
+ return Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
}
/// DeterminePrimaryBase - Determine the primary base of the given class.
@@ -825,7 +840,7 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
setDataSize(getSize());
CharUnits UnpackedBaseAlign =
- Context.toCharUnitsFromBits(Context.Target.getPointerAlign(0));
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
// The maximum field alignment overrides base align.
@@ -1046,6 +1061,45 @@ RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
}
}
+void RecordLayoutBuilder::AddVPointer() {
+ CharUnits PtrWidth =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+ setSize(getSize() + PtrWidth);
+ setDataSize(getSize());
+
+ if (Alignment > PtrWidth) {
+ setSize(getSize() + (Alignment - PtrWidth));
+ setDataSize(getSize());
+ }
+}
+
+bool
+RecordLayoutBuilder::HasNewVirtualFunction(const CXXRecordDecl *RD) const {
+ for (CXXRecordDecl::method_iterator method = RD->method_begin();
+ method != RD->method_end();
+ ++method) {
+ if (method->isVirtual() &&
+ !method->size_overridden_methods()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+RecordLayoutBuilder::HasVBPtr(const CXXRecordDecl *RD) const {
+ if (!RD->getNumBases())
+ return false;
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (!I->isVirtual()) {
+ return false;
+ }
+ }
+ return true;
+}
+
void
RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
const CXXRecordDecl *MostDerivedClass) {
@@ -1157,6 +1211,11 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
IsMsStruct = D->hasAttr<MsStructAttr>();
+ // Honor the default struct packing maximum alignment flag.
+ if (unsigned DefaultMaxFieldAlignment = Context.getLangOptions().PackStruct) {
+ MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment);
+ }
+
// mac68k alignment supersedes maximum field alignment and attribute aligned,
// and forces all structures to have 2-byte alignment. The IBM docs on it
// allude to additional (more complicated) semantics, especially with regard
@@ -1184,6 +1243,11 @@ void RecordLayoutBuilder::Layout(const RecordDecl *D) {
}
void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
+ if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) {
+ MSLayout(RD);
+ return ;
+ }
+
InitializeLayout(RD);
// Lay out the vtable and the non-virtual bases.
@@ -1193,7 +1257,7 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
NonVirtualSize = Context.toCharUnitsFromBits(
llvm::RoundUpToAlignment(getSizeInBits(),
- Context.Target.getCharAlign()));
+ Context.getTargetInfo().getCharAlign()));
NonVirtualAlignment = Alignment;
// Lay out the virtual bases and add the primary virtual base offsets.
@@ -1242,10 +1306,9 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
}
InitializeLayout(D);
- ObjCInterfaceDecl *OI = const_cast<ObjCInterfaceDecl*>(D);
// Layout each ivar sequentially.
- for (ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
- IVD; IVD = IVD->getNextIvar())
+ for (const ObjCIvarDecl *IVD = D->all_declared_ivar_begin(); IVD;
+ IVD = IVD->getNextIvar())
LayoutField(IVD);
// Finally, round the size of the total struct up to the alignment of the
@@ -1271,8 +1334,8 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
continue;
// FIXME. streamline these conditions into a simple one.
else if (Context.BitfieldFollowsBitfield(FD, LastFD) ||
- Context.BitfieldFollowsNoneBitfield(FD, LastFD) ||
- Context.NoneBitfieldFollowsBitfield(FD, LastFD)) {
+ Context.BitfieldFollowsNonBitfield(FD, LastFD) ||
+ Context.NonBitfieldFollowsBitfield(FD, LastFD)) {
// 1) Adjacent bit fields are packed into the same 1-, 2-, or
// 4-byte allocation unit if the integral types are the same
// size and if the next bit field fits into the current
@@ -1299,14 +1362,14 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
if (TypeSizeLastFD != TypeSize) {
if (RemainingInAlignment &&
LastFD && LastFD->isBitField() &&
- LastFD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) {
+ LastFD->getBitWidthValue(Context)) {
// If previous field was a bitfield with some remaining unfilled
// bits, pad the field so current field starts on its type boundary.
uint64_t FieldOffset =
getDataSizeInBits() - UnfilledBitsInLastByte;
uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset;
setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
- Context.Target.getCharAlign()));
+ Context.getTargetInfo().getCharAlign()));
setSize(std::max(getSizeInBits(), getDataSizeInBits()));
RemainingInAlignment = 0;
}
@@ -1325,13 +1388,12 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
uint64_t NewSizeInBits =
llvm::RoundUpToAlignment(UnpaddedFieldOffset, FieldAlign);
setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
- Context.Target.getCharAlign()));
+ Context.getTargetInfo().getCharAlign()));
UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
setSize(std::max(getSizeInBits(), getDataSizeInBits()));
}
if (FD->isBitField()) {
- uint64_t FieldSize =
- FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
+ uint64_t FieldSize = FD->getBitWidthValue(Context);
assert (FieldSize > 0 && "LayoutFields - ms_struct layout");
if (RemainingInAlignment < FieldSize)
RemainingInAlignment = TypeSize - FieldSize;
@@ -1340,8 +1402,7 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
}
}
else if (FD->isBitField()) {
- uint64_t FieldSize =
- FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
+ uint64_t FieldSize = FD->getBitWidthValue(Context);
std::pair<uint64_t, unsigned> FieldInfo =
Context.getTypeInfo(FD->getType());
uint64_t TypeSize = FieldInfo.first;
@@ -1349,18 +1410,23 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
}
LastFD = FD;
}
+ else if (!Context.getTargetInfo().useBitFieldTypeAlignment() &&
+ Context.getTargetInfo().useZeroLengthBitfieldAlignment()) {
+ FieldDecl *FD = (*Field);
+ if (FD->isBitField() && FD->getBitWidthValue(Context) == 0)
+ ZeroLengthBitfield = FD;
+ }
LayoutField(*Field);
}
if (IsMsStruct && RemainingInAlignment &&
- LastFD && LastFD->isBitField() &&
- LastFD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) {
+ LastFD && LastFD->isBitField() && LastFD->getBitWidthValue(Context)) {
// If we ended a bitfield before the full length of the type then
// pad the struct out to the full length of the last type.
uint64_t FieldOffset =
getDataSizeInBits() - UnfilledBitsInLastByte;
uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset;
setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
- Context.Target.getCharAlign()));
+ Context.getTargetInfo().getCharAlign()));
setSize(std::max(getSizeInBits(), getDataSizeInBits()));
}
}
@@ -1405,15 +1471,15 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
setDataSize(std::max(getDataSizeInBits(), FieldSize));
FieldOffset = 0;
} else {
- // The bitfield is allocated starting at the next offset aligned appropriately
- // for T', with length n bits.
+ // The bitfield is allocated starting at the next offset aligned
+ // appropriately for T', with length n bits.
FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(),
Context.toBits(TypeAlign));
uint64_t NewSizeInBits = FieldOffset + FieldSize;
setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
- Context.Target.getCharAlign()));
+ Context.getTargetInfo().getCharAlign()));
UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
}
@@ -1434,7 +1500,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset;
- uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
+ uint64_t FieldSize = D->getBitWidthValue(Context);
std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType());
uint64_t TypeSize = FieldInfo.first;
@@ -1443,21 +1509,32 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// This check is needed for 'long long' in -m32 mode.
if (IsMsStruct && (TypeSize > FieldAlign))
FieldAlign = TypeSize;
-
+
if (ZeroLengthBitfield) {
- // If a zero-length bitfield is inserted after a bitfield,
- // and the alignment of the zero-length bitfield is
- // greater than the member that follows it, `bar', `bar'
- // will be aligned as the type of the zero-length bitfield.
- if (ZeroLengthBitfield != D) {
- std::pair<uint64_t, unsigned> FieldInfo =
- Context.getTypeInfo(ZeroLengthBitfield->getType());
- unsigned ZeroLengthBitfieldAlignment = FieldInfo.second;
- // Ignore alignment of subsequent zero-length bitfields.
- if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0))
- FieldAlign = ZeroLengthBitfieldAlignment;
- if (FieldSize)
- ZeroLengthBitfield = 0;
+ std::pair<uint64_t, unsigned> FieldInfo;
+ unsigned ZeroLengthBitfieldAlignment;
+ if (IsMsStruct) {
+ // If a zero-length bitfield is inserted after a bitfield,
+ // and the alignment of the zero-length bitfield is
+ // greater than the member that follows it, `bar', `bar'
+ // will be aligned as the type of the zero-length bitfield.
+ if (ZeroLengthBitfield != D) {
+ FieldInfo = Context.getTypeInfo(ZeroLengthBitfield->getType());
+ ZeroLengthBitfieldAlignment = FieldInfo.second;
+ // Ignore alignment of subsequent zero-length bitfields.
+ if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0))
+ FieldAlign = ZeroLengthBitfieldAlignment;
+ if (FieldSize)
+ ZeroLengthBitfield = 0;
+ }
+ } else {
+ // The alignment of a zero-length bitfield affects the alignment
+ // of the next member. The alignment is the max of the zero
+ // length bitfield's alignment and a target specific fixed value.
+ unsigned ZeroLengthBitfieldBoundary =
+ Context.getTargetInfo().getZeroLengthBitfieldBoundary();
+ if (ZeroLengthBitfieldBoundary > FieldAlign)
+ FieldAlign = ZeroLengthBitfieldBoundary;
}
}
@@ -1470,10 +1547,11 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// was unnecessary (-Wpacked).
unsigned UnpackedFieldAlign = FieldAlign;
uint64_t UnpackedFieldOffset = FieldOffset;
- if (!Context.Target.useBitFieldTypeAlignment())
+ if (!Context.getTargetInfo().useBitFieldTypeAlignment() && !ZeroLengthBitfield)
UnpackedFieldAlign = 1;
- if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
+ if (FieldPacked ||
+ (!Context.getTargetInfo().useBitFieldTypeAlignment() && !ZeroLengthBitfield))
FieldAlign = 1;
FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
UnpackedFieldAlign = std::max(UnpackedFieldAlign, D->getMaxAlignment());
@@ -1494,10 +1572,14 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
UnpackedFieldAlign);
- // Padding members don't affect overall alignment.
- if (!D->getIdentifier())
+ // Padding members don't affect overall alignment, unless zero length bitfield
+ // alignment is enabled.
+ if (!D->getIdentifier() && !Context.getTargetInfo().useZeroLengthBitfieldAlignment())
FieldAlign = UnpackedFieldAlign = 1;
+ if (!IsMsStruct)
+ ZeroLengthBitfield = 0;
+
// Place this field at the current location.
FieldOffsets.push_back(FieldOffset);
@@ -1512,7 +1594,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
uint64_t NewSizeInBits = FieldOffset + FieldSize;
setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
- Context.Target.getCharAlign()));
+ Context.getTargetInfo().getCharAlign()));
UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
}
@@ -1552,25 +1634,36 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
} else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
unsigned AS = RT->getPointeeType().getAddressSpace();
FieldSize =
- Context.toCharUnitsFromBits(Context.Target.getPointerWidth(AS));
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(AS));
FieldAlign =
- Context.toCharUnitsFromBits(Context.Target.getPointerAlign(AS));
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(AS));
} else {
std::pair<CharUnits, CharUnits> FieldInfo =
Context.getTypeInfoInChars(D->getType());
FieldSize = FieldInfo.first;
FieldAlign = FieldInfo.second;
-
+
if (ZeroLengthBitfield) {
- // If a zero-length bitfield is inserted after a bitfield,
- // and the alignment of the zero-length bitfield is
- // greater than the member that follows it, `bar', `bar'
- // will be aligned as the type of the zero-length bitfield.
- std::pair<CharUnits, CharUnits> FieldInfo =
- Context.getTypeInfoInChars(ZeroLengthBitfield->getType());
- CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second;
- if (ZeroLengthBitfieldAlignment > FieldAlign)
- FieldAlign = ZeroLengthBitfieldAlignment;
+ CharUnits ZeroLengthBitfieldBoundary =
+ Context.toCharUnitsFromBits(
+ Context.getTargetInfo().getZeroLengthBitfieldBoundary());
+ if (ZeroLengthBitfieldBoundary == CharUnits::Zero()) {
+ // If a zero-length bitfield is inserted after a bitfield,
+ // and the alignment of the zero-length bitfield is
+ // greater than the member that follows it, `bar', `bar'
+ // will be aligned as the type of the zero-length bitfield.
+ std::pair<CharUnits, CharUnits> FieldInfo =
+ Context.getTypeInfoInChars(ZeroLengthBitfield->getType());
+ CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second;
+ if (ZeroLengthBitfieldAlignment > FieldAlign)
+ FieldAlign = ZeroLengthBitfieldAlignment;
+ } else if (ZeroLengthBitfieldBoundary > FieldAlign) {
+ // Align 'bar' based on a fixed alignment specified by the target.
+ assert(Context.getTargetInfo().useZeroLengthBitfieldAlignment() &&
+ "ZeroLengthBitfieldBoundary should only be used in conjunction"
+ " with useZeroLengthBitfieldAlignment.");
+ FieldAlign = ZeroLengthBitfieldBoundary;
+ }
ZeroLengthBitfield = 0;
}
@@ -1641,6 +1734,104 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
UpdateAlignment(FieldAlign, UnpackedFieldAlign);
}
+void RecordLayoutBuilder::MSLayoutVirtualBases(const CXXRecordDecl *RD) {
+
+ if (!RD->getNumVBases())
+ return;
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I) {
+
+ const CXXRecordDecl* BaseDecl = I->getType()->getAsCXXRecordDecl();
+ const BaseSubobjectInfo* BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
+
+ assert(BaseInfo && "Did not find virtual base info!");
+
+ LayoutVirtualBase(BaseInfo);
+ }
+}
+
+void RecordLayoutBuilder::MSLayout(const CXXRecordDecl *RD) {
+
+ bool IsVBPtrAddedToLayout = false;
+
+ InitializeLayout(RD);
+
+ if (HasVBPtr(RD)) {
+ // If all bases are virtual and the class declares a new virtual function,
+ // MSVC builds a vfptr.
+ if (HasNewVirtualFunction(RD)) {
+ AddVPointer();
+ }
+
+ VBPtrOffset = getSize();
+ AddVPointer();
+ IsVBPtrAddedToLayout = true;
+
+ ComputeBaseSubobjectInfo(RD);
+ } else {
+ LayoutNonVirtualBases(RD);
+ }
+
+ if (RD->getNumVBases() &&
+ !IsVBPtrAddedToLayout) {
+ // Add vbptr.
+ VBPtrOffset = getSize();
+ AddVPointer();
+ }
+
+ LayoutFields(RD);
+
+ NonVirtualSize = Context.toCharUnitsFromBits(
+ llvm::RoundUpToAlignment(getSizeInBits(),
+ Context.getTargetInfo().getCharAlign()));
+ NonVirtualAlignment = Alignment;
+
+ if (NonVirtualSize != NonVirtualSize.RoundUpToAlignment(Alignment)) {
+ CharUnits AlignMember =
+ NonVirtualSize.RoundUpToAlignment(Alignment) - NonVirtualSize;
+
+ setSize(getSize() + AlignMember);
+ setDataSize(getSize());
+
+ NonVirtualSize = Context.toCharUnitsFromBits(
+ llvm::RoundUpToAlignment(getSizeInBits(),
+ Context.getTargetInfo().getCharAlign()));
+ }
+
+ MSLayoutVirtualBases(RD);
+
+ VisitedVirtualBases.clear();
+
+ // Finally, round the size of the total struct up to the alignment of the
+ // struct itself.
+ if (!RD->getNumVBases())
+ FinishLayout(RD);
+
+#ifndef NDEBUG
+ // Check that we have base offsets for all 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());
+
+ assert(Bases.count(BaseDecl) && "Did not find base offset!");
+ }
+
+ // And all virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ assert(VBases.count(BaseDecl) && "Did not find base offset!");
+ }
+#endif
+}
+
void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
// In C++, records cannot be of size 0.
if (Context.getLangOptions().CPlusPlus && getSizeInBits() == 0) {
@@ -1663,7 +1854,7 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits);
setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment)));
- unsigned CharBitNum = Context.Target.getCharWidth();
+ unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
// Warn if padding was introduced to the struct/class/union.
if (getSizeInBits() > UnpaddedSize) {
@@ -1718,7 +1909,12 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
if (isa<ObjCIvarDecl>(D))
return;
- unsigned CharBitNum = Context.Target.getCharWidth();
+ // Don't warn about structs created without a SourceLocation. This can
+ // be done by clients of the AST, such as codegen.
+ if (D->getLocation().isInvalid())
+ return;
+
+ unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
// Warn if padding was introduced to the struct/class.
if (!IsUnion && Offset > UnpaddedOffset) {
@@ -1802,36 +1998,18 @@ RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) {
return Context.getDiagnostics().Report(Loc, DiagID);
}
-namespace {
- // This class implements layout specific to the Microsoft ABI.
- class MSRecordLayoutBuilder : public RecordLayoutBuilder {
- public:
- MSRecordLayoutBuilder(const ASTContext& Ctx,
- EmptySubobjectMap *EmptySubobjects) :
- RecordLayoutBuilder(Ctx, EmptySubobjects) {}
-
- virtual CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const;
- };
-}
-
-CharUnits
-MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
- // We should reserve space for two pointers if the class has both
- // virtual functions and virtual bases.
- CharUnits PointerWidth =
- Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0));
- if (RD->isPolymorphic() && RD->getNumVBases() > 0)
- return 2 * PointerWidth;
- return PointerWidth;
-}
-
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
const ASTRecordLayout &
ASTContext::getASTRecordLayout(const RecordDecl *D) const {
+ // These asserts test different things. A record has a definition
+ // as soon as we begin to parse the definition. That definition is
+ // not a complete definition (which is what isDefinition() tests)
+ // until we *finish* parsing the definition.
D = D->getDefinition();
assert(D && "Cannot get layout of forward declarations!");
+ assert(D->isCompleteDefinition() && "Cannot layout type before complete!");
// Look up this layout, if already laid out, return what we have.
// Note that we can't save a reference to the entry because this function
@@ -1844,25 +2022,44 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
EmptySubobjectMap EmptySubobjects(*this, RD);
- // When compiling for Microsoft, use the special MS builder.
llvm::OwningPtr<RecordLayoutBuilder> Builder;
- switch (Target.getCXXABI()) {
- default:
- Builder.reset(new RecordLayoutBuilder(*this, &EmptySubobjects));
- break;
- case CXXABI_Microsoft:
- Builder.reset(new MSRecordLayoutBuilder(*this, &EmptySubobjects));
- }
+ CharUnits TargetAlign = CharUnits::One();
+
+ Builder.reset(new RecordLayoutBuilder(*this,
+ &EmptySubobjects,
+ TargetAlign));
+
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<RecordLayoutBuilder>
RecordBuilderCleanup(Builder.get());
Builder->Layout(RD);
+ TargetAlign = Builder->getAligment();
+
+ if (getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
+ TargetAlign.getQuantity() > 4) {
+ // MSVC rounds the vtable pointer to the struct alignment in what must
+ // be a multi-pass operation. For now, let the builder figure out the
+ // alignment and recalculate the layout once its known.
+ Builder.reset(new RecordLayoutBuilder(*this,
+ &EmptySubobjects,
+ TargetAlign));
+
+ Builder->Layout(RD);
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<RecordLayoutBuilder>
+ RecordBuilderCleanup(Builder.get());
+ }
+
// FIXME: This is not always correct. See the part about bitfields at
// http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
// FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
- bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
+ // This does not affect the calculations of MSVC layouts
+ bool IsPODForThePurposeOfLayout =
+ (getTargetInfo().getCXXABI() == CXXABI_Microsoft) ||
+ cast<CXXRecordDecl>(D)->isPOD();
// FIXME: This should be done in FinalizeLayout.
CharUnits DataSize =
@@ -1873,6 +2070,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
NewEntry =
new (*this) ASTRecordLayout(*this, Builder->getSize(),
Builder->Alignment,
+ Builder->GetVBPtrOffset(),
DataSize,
Builder->FieldOffsets.data(),
Builder->FieldOffsets.size(),
@@ -1883,7 +2081,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
Builder->PrimaryBaseIsVirtual,
Builder->Bases, Builder->VBases);
} else {
- RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
+ RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0, CharUnits::One());
Builder.Layout(D);
NewEntry =
@@ -1915,8 +2113,8 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
return Entry;
}
-/// getInterfaceLayoutImpl - Get or compute information about the
-/// layout of the given interface.
+/// getObjCLayout - Get or compute information about the layout of the
+/// given interface.
///
/// \param Impl - If given, also include the layout of the interface's
/// implementation. This may differ by including synthesized ivars.
@@ -1942,7 +2140,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
return getObjCLayout(D, 0);
}
- RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
+ RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0, CharUnits::One());
Builder.Layout(D);
const ASTRecordLayout *NewEntry =
@@ -1957,13 +2155,13 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
return *NewEntry;
}
-static void PrintOffset(llvm::raw_ostream &OS,
+static void PrintOffset(raw_ostream &OS,
CharUnits Offset, unsigned IndentLevel) {
OS << llvm::format("%4d | ", Offset.getQuantity());
OS.indent(IndentLevel * 2);
}
-static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
+static void DumpCXXRecordLayout(raw_ostream &OS,
const CXXRecordDecl *RD, const ASTContext &C,
CharUnits Offset,
unsigned IndentLevel,
@@ -1982,12 +2180,22 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
IndentLevel++;
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+ bool HasVbptr = Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1);
// Vtable pointer.
if (RD->isDynamicClass() && !PrimaryBase) {
PrintOffset(OS, Offset, IndentLevel);
- OS << '(' << RD << " vtable pointer)\n";
+ OS << '(' << *RD << " vtable pointer)\n";
+ }
+
+ if (HasVbptr && !PrimaryBase) {
+ PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
+ OS << '(' << *RD << " vbtable pointer)\n";
+
+ // one vbtable per class
+ HasVbptr = false;
}
+
// Dump (non-virtual) bases
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
@@ -2005,6 +2213,11 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
Base == PrimaryBase ? "(primary base)" : "(base)",
/*IncludeVirtualBases=*/false);
}
+ // vbptr
+ if (HasVbptr) {
+ PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
+ OS << '(' << *RD << " vbtable pointer)\n";
+ }
// Dump fields.
uint64_t FieldNo = 0;
@@ -2024,7 +2237,7 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
}
PrintOffset(OS, FieldOffset, IndentLevel);
- OS << Field->getType().getAsString() << ' ' << Field << '\n';
+ OS << Field->getType().getAsString() << ' ' << *Field << '\n';
}
if (!IncludeVirtualBases)
@@ -2053,7 +2266,7 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
}
void ASTContext::DumpRecordLayout(const RecordDecl *RD,
- llvm::raw_ostream &OS) const {
+ raw_ostream &OS) const {
const ASTRecordLayout &Info = getASTRecordLayout(RD);
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
diff --git a/lib/AST/SelectorLocationsKind.cpp b/lib/AST/SelectorLocationsKind.cpp
new file mode 100644
index 000000000000..671207a7f2d9
--- /dev/null
+++ b/lib/AST/SelectorLocationsKind.cpp
@@ -0,0 +1,128 @@
+//===--- SelectorLocationsKind.cpp - Kind of selector locations -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Describes whether the identifier locations for a selector are "standard"
+// or not.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/SelectorLocationsKind.h"
+#include "clang/AST/Expr.h"
+
+using namespace clang;
+
+static SourceLocation getStandardSelLoc(unsigned Index,
+ Selector Sel,
+ bool WithArgSpace,
+ SourceLocation ArgLoc,
+ SourceLocation EndLoc) {
+ unsigned NumSelArgs = Sel.getNumArgs();
+ if (NumSelArgs == 0) {
+ assert(Index == 0);
+ if (EndLoc.isInvalid())
+ return SourceLocation();
+ IdentifierInfo *II = Sel.getIdentifierInfoForSlot(0);
+ unsigned Len = II ? II->getLength() : 0;
+ return EndLoc.getLocWithOffset(-Len);
+ }
+
+ assert(Index < NumSelArgs);
+ if (ArgLoc.isInvalid())
+ return SourceLocation();
+ IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Index);
+ unsigned Len = /* selector id */ (II ? II->getLength() : 0) + /* ':' */ 1;
+ if (WithArgSpace)
+ ++Len;
+ return ArgLoc.getLocWithOffset(-Len);
+}
+
+namespace {
+
+template <typename T>
+SourceLocation getArgLoc(T* Arg);
+
+template <>
+SourceLocation getArgLoc<Expr>(Expr *Arg) {
+ return Arg->getLocStart();
+}
+
+template <>
+SourceLocation getArgLoc<ParmVarDecl>(ParmVarDecl *Arg) {
+ SourceLocation Loc = Arg->getLocStart();
+ if (Loc.isInvalid())
+ return Loc;
+ // -1 to point to left paren of the method parameter's type.
+ return Loc.getLocWithOffset(-1);
+}
+
+template <typename T>
+SourceLocation getArgLoc(unsigned Index, ArrayRef<T*> Args) {
+ return Index < Args.size() ? getArgLoc(Args[Index]) : SourceLocation();
+}
+
+template <typename T>
+SelectorLocationsKind hasStandardSelLocs(Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ArrayRef<T *> Args,
+ SourceLocation EndLoc) {
+ // Are selector locations in standard position with no space between args ?
+ unsigned i;
+ for (i = 0; i != SelLocs.size(); ++i) {
+ if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/false,
+ Args, EndLoc))
+ break;
+ }
+ if (i == SelLocs.size())
+ return SelLoc_StandardNoSpace;
+
+ // Are selector locations in standard position with space between args ?
+ for (i = 0; i != SelLocs.size(); ++i) {
+ if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/true,
+ Args, EndLoc))
+ return SelLoc_NonStandard;
+ }
+
+ return SelLoc_StandardWithSpace;
+}
+
+} // anonymous namespace
+
+SelectorLocationsKind
+clang::hasStandardSelectorLocs(Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ArrayRef<Expr *> Args,
+ SourceLocation EndLoc) {
+ return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc);
+}
+
+SourceLocation clang::getStandardSelectorLoc(unsigned Index,
+ Selector Sel,
+ bool WithArgSpace,
+ ArrayRef<Expr *> Args,
+ SourceLocation EndLoc) {
+ return getStandardSelLoc(Index, Sel, WithArgSpace,
+ getArgLoc(Index, Args), EndLoc);
+}
+
+SelectorLocationsKind
+clang::hasStandardSelectorLocs(Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ArrayRef<ParmVarDecl *> Args,
+ SourceLocation EndLoc) {
+ return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc);
+}
+
+SourceLocation clang::getStandardSelectorLoc(unsigned Index,
+ Selector Sel,
+ bool WithArgSpace,
+ ArrayRef<ParmVarDecl *> Args,
+ SourceLocation EndLoc) {
+ return getStandardSelLoc(Index, Sel, WithArgSpace,
+ getArgLoc(Index, Args), EndLoc);
+}
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index fd6f21d43b59..e7b87e4db679 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -97,6 +97,22 @@ Stmt *Stmt::IgnoreImplicit() {
return s;
}
+/// \brief Strip off all label-like statements.
+///
+/// This will strip off label statements, case statements, and default
+/// statements recursively.
+const Stmt *Stmt::stripLabelLikeStatements() const {
+ const Stmt *S = this;
+ while (true) {
+ if (const LabelStmt *LS = dyn_cast<LabelStmt>(S))
+ S = LS->getSubStmt();
+ else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))
+ S = SC->getSubStmt();
+ else
+ return S;
+ }
+}
+
namespace {
struct good {};
struct bad {};
@@ -214,7 +230,7 @@ Expr *AsmStmt::getOutputExpr(unsigned i) {
/// getOutputConstraint - Return the constraint string for the specified
/// output operand. All output constraints are known to be non-empty (either
/// '=' or '+').
-llvm::StringRef AsmStmt::getOutputConstraint(unsigned i) const {
+StringRef AsmStmt::getOutputConstraint(unsigned i) const {
return getOutputConstraintLiteral(i)->getString();
}
@@ -238,7 +254,7 @@ void AsmStmt::setInputExpr(unsigned i, Expr *E) {
/// getInputConstraint - Return the specified input constraint. Unlike output
/// constraints, these can be empty.
-llvm::StringRef AsmStmt::getInputConstraint(unsigned i) const {
+StringRef AsmStmt::getInputConstraint(unsigned i) const {
return getInputConstraintLiteral(i)->getString();
}
@@ -277,7 +293,7 @@ void AsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C,
/// getNamedOperand - Given a symbolic operand reference like %[foo],
/// translate this into a numeric value needed to reference the same operand.
/// This returns -1 if the operand name is invalid.
-int AsmStmt::getNamedOperand(llvm::StringRef SymbolicName) const {
+int AsmStmt::getNamedOperand(StringRef SymbolicName) const {
unsigned NumPlusOperands = 0;
// Check if this is an output operand.
@@ -297,9 +313,9 @@ int AsmStmt::getNamedOperand(llvm::StringRef SymbolicName) const {
/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
/// it into pieces. If the asm string is erroneous, emit errors and return
/// true, otherwise return false.
-unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
+unsigned AsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
ASTContext &C, unsigned &DiagOffs) const {
- llvm::StringRef Str = getAsmString()->getString();
+ StringRef Str = getAsmString()->getString();
const char *StrStart = Str.begin();
const char *StrEnd = Str.end();
const char *CurPtr = StrStart;
@@ -326,7 +342,7 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
// asm string.
std::string CurStringPiece;
- bool HasVariants = !C.Target.hasNoAsmVariants();
+ bool HasVariants = !C.getTargetInfo().hasNoAsmVariants();
while (1) {
// Done with the string?
@@ -416,7 +432,7 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
if (NameEnd == CurPtr)
return diag::err_asm_empty_symbolic_operand_name;
- llvm::StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
+ StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
int N = getNamedOperand(SymbolicName);
if (N == -1) {
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index fb024f33ab30..2968739c227a 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -27,7 +27,7 @@ using namespace clang;
namespace {
class StmtDumper : public StmtVisitor<StmtDumper> {
SourceManager *SM;
- llvm::raw_ostream &OS;
+ raw_ostream &OS;
unsigned IndentLevel;
/// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump
@@ -41,7 +41,7 @@ namespace {
unsigned LastLocLine;
public:
- StmtDumper(SourceManager *sm, llvm::raw_ostream &os, unsigned maxDepth)
+ StmtDumper(SourceManager *sm, raw_ostream &os, unsigned maxDepth)
: SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) {
LastLocFilename = "";
LastLocLine = ~0U;
@@ -235,9 +235,9 @@ void StmtDumper::DumpDeclarator(Decl *D) {
// nodes are where they need to be.
if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) {
OS << "\"typedef " << localType->getUnderlyingType().getAsString()
- << ' ' << localType << '"';
+ << ' ' << *localType << '"';
} else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) {
- OS << "\"using " << localType << " = "
+ OS << "\"using " << *localType << " = "
<< localType->getUnderlyingType().getAsString() << '"';
} else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
OS << "\"";
@@ -294,7 +294,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
DumpSubTree(SAD->getMessage());
OS << ");\"";
} else {
- assert(0 && "Unexpected decl");
+ llvm_unreachable("Unexpected decl");
}
}
@@ -333,7 +333,7 @@ void StmtDumper::VisitExpr(Expr *Node) {
DumpExpr(Node);
}
-static void DumpBasePath(llvm::raw_ostream &OS, CastExpr *Node) {
+static void DumpBasePath(raw_ostream &OS, CastExpr *Node) {
if (Node->path_empty())
return;
@@ -407,7 +407,7 @@ void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
DumpExpr(Node);
OS << " " << Node->getDecl()->getDeclKindName()
- << "Decl='" << Node->getDecl()
+ << "Decl='" << *Node->getDecl()
<< "' " << (void*)Node->getDecl();
if (Node->isFreeIvar())
OS << " isFreeIvar";
@@ -416,7 +416,7 @@ void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) {
DumpExpr(Node);
switch (Node->getIdentType()) {
- default: assert(0 && "unknown case");
+ default: llvm_unreachable("unknown case");
case PredefinedExpr::Func: OS << " __func__"; break;
case PredefinedExpr::Function: OS << " __FUNCTION__"; break;
case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
@@ -443,8 +443,13 @@ void StmtDumper::VisitStringLiteral(StringLiteral *Str) {
DumpExpr(Str);
// FIXME: this doesn't print wstrings right.
OS << " ";
- if (Str->isWide())
- OS << "L";
+ switch (Str->getKind()) {
+ case StringLiteral::Ascii: break; // No prefix
+ case StringLiteral::Wide: OS << 'L'; break;
+ case StringLiteral::UTF8: OS << "u8"; break;
+ case StringLiteral::UTF16: OS << 'u'; break;
+ case StringLiteral::UTF32: OS << 'U'; break;
+ }
OS << '"';
OS.write_escaped(Str->getString());
OS << '"';
@@ -475,7 +480,7 @@ void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
DumpExpr(Node);
OS << " " << (Node->isArrow() ? "->" : ".")
- << Node->getMemberDecl() << ' '
+ << *Node->getMemberDecl() << ' '
<< (void*)Node->getMemberDecl();
}
void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
@@ -552,7 +557,8 @@ void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) {
void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
DumpExpr(Node);
- OS << " functional cast to " << Node->getTypeAsWritten().getAsString();
+ OS << " functional cast to " << Node->getTypeAsWritten().getAsString()
+ << " <" << Node->getCastKindName() << ">";
}
void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) {
@@ -637,7 +643,7 @@ void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
DumpExpr(Node);
- OS << ' ' << Node->getProtocol();
+ OS << ' ' <<* Node->getProtocol();
}
void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
@@ -656,7 +662,7 @@ void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
OS << "(null)";
OS << "\"";
} else {
- OS << " Kind=PropertyRef Property=\"" << Node->getExplicitProperty() << '"';
+ OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"';
}
if (Node->isSuperReceiver())
@@ -674,7 +680,7 @@ void Stmt::dump(SourceManager &SM) const {
dump(llvm::errs(), SM);
}
-void Stmt::dump(llvm::raw_ostream &OS, SourceManager &SM) const {
+void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
StmtDumper P(&SM, OS, 4);
P.DumpSubTree(const_cast<Stmt*>(this));
OS << "\n";
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index f705a84c7cf4..daaa354ac342 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -28,14 +28,14 @@ using namespace clang;
namespace {
class StmtPrinter : public StmtVisitor<StmtPrinter> {
- llvm::raw_ostream &OS;
+ raw_ostream &OS;
ASTContext &Context;
unsigned IndentLevel;
clang::PrinterHelper* Helper;
PrintingPolicy Policy;
public:
- StmtPrinter(llvm::raw_ostream &os, ASTContext &C, PrinterHelper* helper,
+ StmtPrinter(raw_ostream &os, ASTContext &C, PrinterHelper* helper,
const PrintingPolicy &Policy,
unsigned Indentation = 0)
: OS(os), Context(C), IndentLevel(Indentation), Helper(helper),
@@ -76,7 +76,7 @@ namespace {
OS << "<null expr>";
}
- llvm::raw_ostream &Indent(int Delta = 0) {
+ raw_ostream &Indent(int Delta = 0) {
for (int i = 0, e = IndentLevel+Delta; i < e; ++i)
OS << " ";
return OS;
@@ -124,7 +124,7 @@ void StmtPrinter::PrintRawDecl(Decl *D) {
void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) {
DeclStmt::decl_iterator Begin = S->decl_begin(), End = S->decl_end();
- llvm::SmallVector<Decl*, 2> Decls;
+ SmallVector<Decl*, 2> Decls;
for ( ; Begin != End; ++Begin)
Decls.push_back(*Begin);
@@ -564,7 +564,7 @@ void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
}
- OS << Node->getDecl();
+ OS << *Node->getDecl();
}
void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
@@ -584,7 +584,7 @@ void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
switch (Node->getIdentType()) {
default:
- assert(0 && "unknown case");
+ llvm_unreachable("unknown case");
case PredefinedExpr::Func:
OS << "__func__";
break;
@@ -599,8 +599,14 @@ void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
unsigned value = Node->getValue();
- if (Node->isWide())
- OS << "L";
+
+ switch (Node->getKind()) {
+ case CharacterLiteral::Ascii: break; // no prefix.
+ case CharacterLiteral::Wide: OS << 'L'; break;
+ case CharacterLiteral::UTF16: OS << 'u'; break;
+ case CharacterLiteral::UTF32: OS << 'U'; break;
+ }
+
switch (value) {
case '\\':
OS << "'\\\\'";
@@ -652,7 +658,7 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
// Emit suffixes. Integer literals are always a builtin integer type.
switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
- default: assert(0 && "Unexpected type for integer literal!");
+ default: llvm_unreachable("Unexpected type for integer literal!");
case BuiltinType::Int: break; // no suffix.
case BuiltinType::UInt: OS << 'U'; break;
case BuiltinType::Long: OS << 'L'; break;
@@ -662,8 +668,9 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
}
}
void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
- // FIXME: print value more precisely.
- OS << Node->getValueAsApproximateDouble();
+ llvm::SmallString<16> Str;
+ Node->getValue().toString(Str);
+ OS << Str;
}
void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) {
@@ -672,12 +679,18 @@ void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) {
}
void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
- if (Str->isWide()) OS << 'L';
+ switch (Str->getKind()) {
+ case StringLiteral::Ascii: break; // no prefix.
+ case StringLiteral::Wide: OS << 'L'; break;
+ case StringLiteral::UTF8: OS << "u8"; break;
+ case StringLiteral::UTF16: OS << 'u'; break;
+ case StringLiteral::UTF32: OS << 'U'; break;
+ }
OS << '"';
// FIXME: this doesn't print wstrings right.
- llvm::StringRef StrData = Str->getString();
- for (llvm::StringRef::iterator I = StrData.begin(), E = StrData.end();
+ StringRef StrData = Str->getString();
+ for (StringRef::iterator I = StrData.begin(), E = StrData.end();
I != E; ++I) {
unsigned char Char = *I;
@@ -998,6 +1011,59 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
OS << ")";
}
+void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
+ const char *Name = 0;
+ switch (Node->getOp()) {
+ case AtomicExpr::Load:
+ Name = "__atomic_load(";
+ break;
+ case AtomicExpr::Store:
+ Name = "__atomic_store(";
+ break;
+ case AtomicExpr::CmpXchgStrong:
+ Name = "__atomic_compare_exchange_strong(";
+ break;
+ case AtomicExpr::CmpXchgWeak:
+ Name = "__atomic_compare_exchange_weak(";
+ break;
+ case AtomicExpr::Xchg:
+ Name = "__atomic_exchange(";
+ break;
+ case AtomicExpr::Add:
+ Name = "__atomic_fetch_add(";
+ break;
+ case AtomicExpr::Sub:
+ Name = "__atomic_fetch_sub(";
+ break;
+ case AtomicExpr::And:
+ Name = "__atomic_fetch_and(";
+ break;
+ case AtomicExpr::Or:
+ Name = "__atomic_fetch_or(";
+ break;
+ case AtomicExpr::Xor:
+ Name = "__atomic_fetch_xor(";
+ break;
+ }
+ OS << Name;
+ PrintExpr(Node->getPtr());
+ OS << ", ";
+ if (Node->getOp() != AtomicExpr::Load) {
+ PrintExpr(Node->getVal1());
+ OS << ", ";
+ }
+ if (Node->isCmpXChg()) {
+ PrintExpr(Node->getVal2());
+ OS << ", ";
+ }
+ PrintExpr(Node->getOrder());
+ if (Node->isCmpXChg()) {
+ OS << ", ";
+ PrintExpr(Node->getOrderFail());
+ }
+ OS << ")";
+}
+
// C++
void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
const char *OpStrings[NUM_OVERLOADED_OPERATORS] = {
@@ -1039,7 +1105,7 @@ void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
OS << ' ' << OpStrings[Kind] << ' ';
PrintExpr(Node->getArg(1));
} else {
- assert(false && "unknown overloaded operator");
+ llvm_unreachable("unknown overloaded operator");
}
}
@@ -1438,7 +1504,7 @@ void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
}
void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
- OS << "@protocol(" << Node->getProtocol() << ')';
+ OS << "@protocol(" << *Node->getProtocol() << ')';
}
void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
@@ -1520,7 +1586,7 @@ void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
}
void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) {
- OS << Node->getDecl();
+ OS << *Node->getDecl();
}
void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {}
@@ -1541,7 +1607,7 @@ void Stmt::dumpPretty(ASTContext& Context) const {
PrintingPolicy(Context.getLangOptions()));
}
-void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context,
+void Stmt::printPretty(raw_ostream &OS, ASTContext& Context,
PrinterHelper* Helper,
const PrintingPolicy &Policy,
unsigned Indentation) const {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 120c9e50a92a..214378a974a6 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -252,7 +252,7 @@ void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) {
void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) {
VisitExpr(S);
- ID.AddBoolean(S->isWide());
+ ID.AddInteger(S->getKind());
ID.AddInteger(S->getValue());
}
@@ -269,7 +269,7 @@ void StmtProfiler::VisitImaginaryLiteral(const ImaginaryLiteral *S) {
void StmtProfiler::VisitStringLiteral(const StringLiteral *S) {
VisitExpr(S);
ID.AddString(S->getString());
- ID.AddBoolean(S->isWide());
+ ID.AddInteger(S->getKind());
}
void StmtProfiler::VisitParenExpr(const ParenExpr *S) {
@@ -468,6 +468,11 @@ void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) {
}
}
+void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getOp());
+}
+
static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
UnaryOperatorKind &UnaryOp,
BinaryOperatorKind &BinaryOp) {
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 56c6e7bc47c1..0c011a8ef090 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -33,7 +33,7 @@ using namespace clang;
///
/// \param Out the raw_ostream instance to use for printing.
static void printIntegral(const TemplateArgument &TemplArg,
- llvm::raw_ostream &Out) {
+ raw_ostream &Out) {
const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
const llvm::APSInt *Val = TemplArg.getAsIntegral();
@@ -68,8 +68,7 @@ TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
bool TemplateArgument::isDependent() const {
switch (getKind()) {
case Null:
- assert(false && "Should not have a NULL template argument");
- return false;
+ llvm_unreachable("Should not have a NULL template argument");
case Type:
return getAsType()->isDependentType();
@@ -107,8 +106,7 @@ bool TemplateArgument::isDependent() const {
bool TemplateArgument::isInstantiationDependent() const {
switch (getKind()) {
case Null:
- assert(false && "Should not have a NULL template argument");
- return false;
+ llvm_unreachable("Should not have a NULL template argument");
case Type:
return getAsType()->isInstantiationDependentType();
@@ -309,7 +307,7 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
}
void TemplateArgument::print(const PrintingPolicy &Policy,
- llvm::raw_ostream &Out) const {
+ raw_ostream &Out) const {
switch (getKind()) {
case Null:
Out << "<no value>";
@@ -530,3 +528,65 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
return DB;
}
+
+const ASTTemplateArgumentListInfo *
+ASTTemplateArgumentListInfo::Create(ASTContext &C,
+ const TemplateArgumentListInfo &List) {
+ std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
+ ASTTemplateArgumentListInfo::sizeFor(List);
+ void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
+ ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
+ TAI->initializeFrom(List);
+ return TAI;
+}
+
+void ASTTemplateArgumentListInfo::initializeFrom(
+ const TemplateArgumentListInfo &Info) {
+ LAngleLoc = Info.getLAngleLoc();
+ RAngleLoc = Info.getRAngleLoc();
+ NumTemplateArgs = Info.size();
+
+ TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
+}
+
+void ASTTemplateArgumentListInfo::initializeFrom(
+ const TemplateArgumentListInfo &Info,
+ bool &Dependent,
+ bool &InstantiationDependent,
+ bool &ContainsUnexpandedParameterPack) {
+ LAngleLoc = Info.getLAngleLoc();
+ RAngleLoc = Info.getRAngleLoc();
+ NumTemplateArgs = Info.size();
+
+ TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
+ for (unsigned i = 0; i != NumTemplateArgs; ++i) {
+ Dependent = Dependent || Info[i].getArgument().isDependent();
+ InstantiationDependent = InstantiationDependent ||
+ Info[i].getArgument().isInstantiationDependent();
+ ContainsUnexpandedParameterPack
+ = ContainsUnexpandedParameterPack ||
+ Info[i].getArgument().containsUnexpandedParameterPack();
+
+ new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
+ }
+}
+
+void ASTTemplateArgumentListInfo::copyInto(
+ TemplateArgumentListInfo &Info) const {
+ Info.setLAngleLoc(LAngleLoc);
+ Info.setRAngleLoc(RAngleLoc);
+ for (unsigned I = 0; I != NumTemplateArgs; ++I)
+ Info.addArgument(getTemplateArgs()[I]);
+}
+
+std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
+ return sizeof(ASTTemplateArgumentListInfo) +
+ sizeof(TemplateArgumentLoc) * NumTemplateArgs;
+}
+
+std::size_t ASTTemplateArgumentListInfo::sizeFor(
+ const TemplateArgumentListInfo &Info) {
+ return sizeFor(Info.size());
+}
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
index 1f7b19aae471..a0487ba0593b 100644
--- a/lib/AST/TemplateName.cpp
+++ b/lib/AST/TemplateName.cpp
@@ -125,16 +125,16 @@ bool TemplateName::containsUnexpandedParameterPack() const {
}
void
-TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
+TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
bool SuppressNNS) const {
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
- OS << Template;
+ OS << *Template;
else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
if (!SuppressNNS)
QTN->getQualifier()->print(OS, Policy);
if (QTN->hasTemplateKeyword())
OS << "template ";
- OS << QTN->getDecl();
+ OS << *QTN->getDecl();
} else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
if (!SuppressNNS && DTN->getQualifier())
DTN->getQualifier()->print(OS, Policy);
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 08971eb03421..44eeec004f57 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -42,6 +42,26 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const {
(hasObjCLifetime() && !Other.hasObjCLifetime()));
}
+const IdentifierInfo* QualType::getBaseTypeIdentifier() const {
+ const Type* ty = getTypePtr();
+ NamedDecl *ND = NULL;
+ if (ty->isPointerType() || ty->isReferenceType())
+ return ty->getPointeeType().getBaseTypeIdentifier();
+ else if (ty->isRecordType())
+ ND = ty->getAs<RecordType>()->getDecl();
+ else if (ty->isEnumeralType())
+ ND = ty->getAs<EnumType>()->getDecl();
+ else if (ty->getTypeClass() == Type::Typedef)
+ ND = ty->getAs<TypedefType>()->getDecl();
+ else if (ty->isArrayType())
+ return ty->castAsArrayTypeUnsafe()->
+ getElementType().getBaseTypeIdentifier();
+
+ if (ND)
+ return ND->getIdentifier();
+ return NULL;
+}
+
bool QualType::isConstant(QualType T, ASTContext &Ctx) {
if (T.isConstQualified())
return true;
@@ -635,6 +655,18 @@ bool Type::isWideCharType() const {
return false;
}
+bool Type::isChar16Type() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Char16;
+ return false;
+}
+
+bool Type::isChar32Type() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Char32;
+ return false;
+}
+
/// \brief Determine whether this type is any of the built-in character
/// types.
bool Type::isAnyCharacterType() const {
@@ -734,9 +766,16 @@ bool Type::hasUnsignedIntegerRepresentation() const {
return isUnsignedIntegerType();
}
+bool Type::isHalfType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Half;
+ // FIXME: Should we allow complex __fp16? Probably not.
+ return false;
+}
+
bool Type::isFloatingType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
- return BT->getKind() >= BuiltinType::Float &&
+ return BT->getKind() >= BuiltinType::Half &&
BT->getKind() <= BuiltinType::LongDouble;
if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
@@ -801,14 +840,16 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
const Type *T = CanonicalType.getTypePtr();
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
if (BT->getKind() == BuiltinType::Bool) return STK_Bool;
- if (BT->getKind() == BuiltinType::NullPtr) return STK_Pointer;
+ if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer;
if (BT->isInteger()) return STK_Integral;
if (BT->isFloatingPoint()) return STK_Floating;
llvm_unreachable("unknown scalar builtin type");
- } else if (isa<PointerType>(T) ||
- isa<BlockPointerType>(T) ||
- isa<ObjCObjectPointerType>(T)) {
- return STK_Pointer;
+ } else if (isa<PointerType>(T)) {
+ return STK_CPointer;
+ } else if (isa<BlockPointerType>(T)) {
+ return STK_BlockPointer;
+ } else if (isa<ObjCObjectPointerType>(T)) {
+ return STK_ObjCObjectPointer;
} else if (isa<MemberPointerType>(T)) {
return STK_MemberPointer;
} else if (isa<EnumType>(T)) {
@@ -821,7 +862,6 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
}
llvm_unreachable("unknown scalar type");
- return STK_Pointer;
}
/// \brief Determines whether the type is a C++ aggregate type or C
@@ -872,7 +912,7 @@ bool Type::isIncompleteType() const {
case Record:
// A tagged type (struct/union/enum/class) is incomplete if the decl is a
// forward declaration, but not a full definition (C99 6.2.5p22).
- return !cast<TagType>(CanonicalType)->getDecl()->isDefinition();
+ return !cast<TagType>(CanonicalType)->getDecl()->isCompleteDefinition();
case ConstantArray:
// An array is incomplete if its element type is incomplete
// (C++ [dcl.array]p1).
@@ -1073,7 +1113,7 @@ bool Type::isLiteralType() const {
// C++0x [basic.types]p10:
// A type is a literal type if it is:
// [...]
- // -- an array of literal type
+ // -- an array of literal type.
// Extension: variable arrays cannot be literal types, since they're
// runtime-sized.
if (isVariableArrayType())
@@ -1093,33 +1133,31 @@ bool Type::isLiteralType() const {
// C++0x [basic.types]p10:
// A type is a literal type if it is:
// -- a scalar type; or
- // As an extension, Clang treats vector types as Scalar types.
- if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
+ // As an extension, Clang treats vector types as literal types.
+ if (BaseTy->isScalarType() || BaseTy->isVectorType())
+ return true;
// -- a reference type; or
- if (BaseTy->isReferenceType()) return true;
+ if (BaseTy->isReferenceType())
+ return true;
// -- a class type that has all of the following properties:
if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
+ // -- a trivial destructor,
+ // -- every constructor call and full-expression in the
+ // brace-or-equal-initializers for non-static data members (if any)
+ // is a constant expression,
+ // -- it is an aggregate type or has at least one constexpr
+ // constructor or constructor template that is not a copy or move
+ // constructor, and
+ // -- all non-static data members and base classes of literal types
+ //
+ // We resolve DR1361 by ignoring the second bullet.
if (const CXXRecordDecl *ClassDecl =
- dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- // -- a trivial destructor,
- if (!ClassDecl->hasTrivialDestructor()) return false;
- // -- every constructor call and full-expression in the
- // brace-or-equal-initializers for non-static data members (if any)
- // is a constant expression,
- // FIXME: C++0x: Clang doesn't yet support non-static data member
- // declarations with initializers, or constexprs.
- // -- it is an aggregate type or has at least one constexpr
- // constructor or constructor template that is not a copy or move
- // constructor, and
- if (!ClassDecl->isAggregate() &&
- !ClassDecl->hasConstExprNonCopyMoveConstructor())
- return false;
- // -- all non-static data members and base classes of literal types
- if (ClassDecl->hasNonLiteralTypeFieldsOrBases()) return false;
- }
+ dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ return ClassDecl->isLiteral();
return true;
}
+
return false;
}
@@ -1158,7 +1196,7 @@ bool Type::isStandardLayoutType() const {
}
// This is effectively the intersection of isTrivialType and
-// isStandardLayoutType. We implement it dircetly to avoid redundant
+// isStandardLayoutType. We implement it directly to avoid redundant
// conversions from a type to a CXXRecordDecl.
bool QualType::isCXX11PODType(ASTContext &Context) const {
const Type *ty = getTypePtr();
@@ -1426,10 +1464,10 @@ const char *Type::getTypeClassName() const {
return 0;
}
-const char *BuiltinType::getName(const LangOptions &LO) const {
+const char *BuiltinType::getName(const PrintingPolicy &Policy) const {
switch (getKind()) {
case Void: return "void";
- case Bool: return LO.Bool ? "bool" : "_Bool";
+ case Bool: return Policy.Bool ? "bool" : "_Bool";
case Char_S: return "char";
case Char_U: return "char";
case SChar: return "signed char";
@@ -1444,6 +1482,7 @@ const char *BuiltinType::getName(const LangOptions &LO) const {
case ULong: return "unsigned long";
case ULongLong: return "unsigned long long";
case UInt128: return "__uint128_t";
+ case Half: return "half";
case Float: return "float";
case Double: return "double";
case LongDouble: return "long double";
@@ -1481,7 +1520,7 @@ QualType QualType::getNonLValueExprType(ASTContext &Context) const {
return *this;
}
-llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) {
+StringRef FunctionType::getNameForCallConv(CallingConv CC) {
switch (CC) {
case CC_Default:
llvm_unreachable("no name for default cc");
@@ -1716,7 +1755,7 @@ static TagDecl *getInterestingTagDecl(TagDecl *decl) {
for (TagDecl::redecl_iterator I = decl->redecls_begin(),
E = decl->redecls_end();
I != E; ++I) {
- if (I->isDefinition() || I->isBeingDefined())
+ if (I->isCompleteDefinition() || I->isBeingDefined())
return *I;
}
// If there's no definition (not even in progress), return what we have.
@@ -2082,6 +2121,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
return Cache::get(cast<ObjCObjectType>(T)->getBaseType());
case Type::ObjCObjectPointer:
return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
+ case Type::Atomic:
+ return Cache::get(cast<AtomicType>(T)->getValueType());
}
llvm_unreachable("unhandled type class");
@@ -2227,13 +2268,13 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
/// with non-trivial destructors.
const CXXRecordDecl *record =
type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
- if (record && !record->hasTrivialDestructor())
+ if (record && record->hasDefinition() && !record->hasTrivialDestructor())
return DK_cxx_destructor;
return DK_none;
}
-bool QualType::hasTrivialCopyAssignment(ASTContext &Context) const {
+bool QualType::hasTrivialAssignment(ASTContext &Context, bool Copying) const {
switch (getObjCLifetime()) {
case Qualifiers::OCL_None:
break;
@@ -2249,7 +2290,8 @@ bool QualType::hasTrivialCopyAssignment(ASTContext &Context) const {
if (const CXXRecordDecl *Record
= getTypePtr()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
- return Record->hasTrivialCopyAssignment();
+ return Copying ? Record->hasTrivialCopyAssignment() :
+ Record->hasTrivialMoveAssignment();
return true;
}
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 34e7693e3075..8e8b227e1f09 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -206,7 +206,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::Char_S:
return TST_char;
case BuiltinType::Char16:
- return TST_char16;
+ return TST_char16;
case BuiltinType::Char32:
return TST_char32;
case BuiltinType::WChar_S:
@@ -225,6 +225,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::Long:
case BuiltinType::LongLong:
case BuiltinType::Int128:
+ case BuiltinType::Half:
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble:
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index b89d2aa31676..fb7b918ca2fe 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -123,6 +123,7 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
case Type::DependentTemplateSpecialization:
case Type::ObjCObject:
case Type::ObjCInterface:
+ case Type::Atomic:
CanPrefixQualifiers = true;
break;
@@ -205,11 +206,11 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) {
if (S.empty()) {
- S = T->getName(Policy.LangOpts);
+ S = T->getName(Policy);
} else {
// Prefix the basic type, e.g. 'int X'.
S = ' ' + S;
- S = T->getName(Policy.LangOpts) + S;
+ S = T->getName(Policy) + S;
}
}
@@ -581,6 +582,16 @@ void TypePrinter::printAuto(const AutoType *T, std::string &S) {
}
}
+void TypePrinter::printAtomic(const AtomicType *T, std::string &S) {
+ if (!S.empty())
+ S = ' ' + S;
+ std::string Str;
+ IncludeStrongLifetimeRAII Strong(Policy);
+ print(T->getValueType(), Str);
+
+ S = "_Atomic(" + Str + ")" + S;
+}
+
/// Appends the given scope to the end of a string.
void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
if (DC->isTranslationUnit()) return;
diff --git a/lib/AST/VTTBuilder.cpp b/lib/AST/VTTBuilder.cpp
new file mode 100644
index 000000000000..f5ff624cf069
--- /dev/null
+++ b/lib/AST/VTTBuilder.cpp
@@ -0,0 +1,212 @@
+//===--- VTTBuilder.cpp - C++ VTT layout builder --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with generation of the layout of virtual table
+// tables (VTT).
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/VTTBuilder.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/Format.h"
+#include <algorithm>
+#include <cstdio>
+
+using namespace clang;
+
+#define DUMP_OVERRIDERS 0
+
+VTTBuilder::VTTBuilder(ASTContext &Ctx,
+ const CXXRecordDecl *MostDerivedClass,
+ bool GenerateDefinition)
+ : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
+ MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
+ GenerateDefinition(GenerateDefinition) {
+ // Lay out this VTT.
+ LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
+ /*BaseIsVirtual=*/false);
+}
+
+void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
+ const CXXRecordDecl *VTableClass) {
+ // Store the vtable pointer index if we're generating the primary VTT.
+ if (VTableClass == MostDerivedClass) {
+ assert(!SecondaryVirtualPointerIndices.count(Base) &&
+ "A virtual pointer index already exists for this base subobject!");
+ SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
+ }
+
+ if (!GenerateDefinition) {
+ VTTComponents.push_back(VTTComponent());
+ return;
+ }
+
+ VTTComponents.push_back(VTTComponent(VTableIndex, Base));
+}
+
+void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+
+ // Don't layout virtual bases.
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
+ CharUnits BaseOffset = Base.getBaseOffset() +
+ Layout.getBaseClassOffset(BaseDecl);
+
+ // Layout the VTT for this base.
+ LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
+ }
+}
+
+void
+VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ uint64_t VTableIndex,
+ const CXXRecordDecl *VTableClass,
+ VisitedVirtualBasesSetTy &VBases) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ // We're not interested in bases that don't have virtual bases, and not
+ // morally virtual bases.
+ if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
+ return;
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Itanium C++ ABI 2.6.2:
+ // Secondary virtual pointers are present for all bases with either
+ // virtual bases or virtual function declarations overridden along a
+ // virtual path.
+ //
+ // If the base class is not dynamic, we don't want to add it, nor any
+ // of its base classes.
+ if (!BaseDecl->isDynamicClass())
+ continue;
+
+ bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
+ bool BaseDeclIsNonVirtualPrimaryBase = false;
+ CharUnits BaseOffset;
+ if (I->isVirtual()) {
+ // Ignore virtual bases that we've already visited.
+ if (!VBases.insert(BaseDecl))
+ continue;
+
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+ BaseDeclIsMorallyVirtual = true;
+ } else {
+ const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
+
+ BaseOffset = Base.getBaseOffset() +
+ Layout.getBaseClassOffset(BaseDecl);
+
+ if (!Layout.isPrimaryBaseVirtual() &&
+ Layout.getPrimaryBase() == BaseDecl)
+ BaseDeclIsNonVirtualPrimaryBase = true;
+ }
+
+ // Itanium C++ ABI 2.6.2:
+ // Secondary virtual pointers: for each base class X which (a) has virtual
+ // bases or is reachable along a virtual path from D, and (b) is not a
+ // non-virtual primary base, the address of the virtual table for X-in-D
+ // or an appropriate construction virtual table.
+ if (!BaseDeclIsNonVirtualPrimaryBase &&
+ (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
+ // Add the vtable pointer.
+ AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex,
+ VTableClass);
+ }
+
+ // And lay out the secondary virtual pointers for the base class.
+ LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
+ BaseDeclIsMorallyVirtual, VTableIndex,
+ VTableClass, VBases);
+ }
+}
+
+void
+VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ uint64_t VTableIndex) {
+ VisitedVirtualBasesSetTy VBases;
+ LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
+ VTableIndex, Base.getBase(), VBases);
+}
+
+void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this is a virtual base.
+ if (I->isVirtual()) {
+ // Check if we've seen this base before.
+ if (!VBases.insert(BaseDecl))
+ continue;
+
+ CharUnits BaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+
+ LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
+ }
+
+ // We only need to layout virtual VTTs for this base if it actually has
+ // virtual bases.
+ if (BaseDecl->getNumVBases())
+ LayoutVirtualVTTs(BaseDecl, VBases);
+ }
+}
+
+void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ // Itanium C++ ABI 2.6.2:
+ // An array of virtual table addresses, called the VTT, is declared for
+ // each class type that has indirect or direct virtual base classes.
+ if (RD->getNumVBases() == 0)
+ return;
+
+ bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
+
+ if (!IsPrimaryVTT) {
+ // Remember the sub-VTT index.
+ SubVTTIndicies[Base] = VTTComponents.size();
+ }
+
+ uint64_t VTableIndex = VTTVTables.size();
+ VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual));
+
+ // Add the primary vtable pointer.
+ AddVTablePointer(Base, VTableIndex, RD);
+
+ // Add the secondary VTTs.
+ LayoutSecondaryVTTs(Base);
+
+ // Add the secondary virtual pointers.
+ LayoutSecondaryVirtualPointers(Base, VTableIndex);
+
+ // If this is the primary VTT, we want to lay out virtual VTTs as well.
+ if (IsPrimaryVTT) {
+ VisitedVirtualBasesSetTy VBases;
+ LayoutVirtualVTTs(Base.getBase(), VBases);
+ }
+}
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
new file mode 100644
index 000000000000..7765817759a4
--- /dev/null
+++ b/lib/AST/VTableBuilder.cpp
@@ -0,0 +1,2404 @@
+//===--- VTableBuilder.cpp - C++ vtable layout builder --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with generation of the layout of virtual tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/VTableBuilder.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/Format.h"
+#include <algorithm>
+#include <cstdio>
+
+using namespace clang;
+
+#define DUMP_OVERRIDERS 0
+
+namespace {
+
+/// BaseOffset - Represents an offset from a derived class to a direct or
+/// indirect base class.
+struct BaseOffset {
+ /// DerivedClass - The derived class.
+ const CXXRecordDecl *DerivedClass;
+
+ /// VirtualBase - If the path from the derived class to the base class
+ /// involves a virtual base class, this holds its declaration.
+ const CXXRecordDecl *VirtualBase;
+
+ /// NonVirtualOffset - The offset from the derived class to the base class.
+ /// (Or the offset from the virtual base class to the base class, if the
+ /// path from the derived class to the base class involves a virtual base
+ /// class.
+ CharUnits NonVirtualOffset;
+
+ BaseOffset() : DerivedClass(0), VirtualBase(0),
+ NonVirtualOffset(CharUnits::Zero()) { }
+ BaseOffset(const CXXRecordDecl *DerivedClass,
+ const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset)
+ : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
+ NonVirtualOffset(NonVirtualOffset) { }
+
+ bool isEmpty() const { return NonVirtualOffset.isZero() && !VirtualBase; }
+};
+
+/// FinalOverriders - Contains the final overrider member functions for all
+/// member functions in the base subobjects of a class.
+class FinalOverriders {
+public:
+ /// OverriderInfo - Information about a final overrider.
+ struct OverriderInfo {
+ /// Method - The method decl of the overrider.
+ const CXXMethodDecl *Method;
+
+ /// Offset - the base offset of the overrider in the layout class.
+ CharUnits Offset;
+
+ OverriderInfo() : Method(0), Offset(CharUnits::Zero()) { }
+ };
+
+private:
+ /// MostDerivedClass - The most derived class for which the final overriders
+ /// are stored.
+ const CXXRecordDecl *MostDerivedClass;
+
+ /// MostDerivedClassOffset - If we're building final overriders for a
+ /// construction vtable, this holds the offset from the layout class to the
+ /// most derived class.
+ const CharUnits MostDerivedClassOffset;
+
+ /// LayoutClass - The class we're using for layout information. Will be
+ /// different than the most derived class if the final overriders are for a
+ /// construction vtable.
+ const CXXRecordDecl *LayoutClass;
+
+ ASTContext &Context;
+
+ /// MostDerivedClassLayout - the AST record layout of the most derived class.
+ const ASTRecordLayout &MostDerivedClassLayout;
+
+ /// MethodBaseOffsetPairTy - Uniquely identifies a member function
+ /// in a base subobject.
+ typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
+
+ typedef llvm::DenseMap<MethodBaseOffsetPairTy,
+ OverriderInfo> OverridersMapTy;
+
+ /// OverridersMap - The final overriders for all virtual member functions of
+ /// all the base subobjects of the most derived class.
+ OverridersMapTy OverridersMap;
+
+ /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
+ /// as a record decl and a subobject number) and its offsets in the most
+ /// derived class as well as the layout class.
+ typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
+ CharUnits> SubobjectOffsetMapTy;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
+
+ /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
+ /// given base.
+ void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
+ CharUnits OffsetInLayoutClass,
+ SubobjectOffsetMapTy &SubobjectOffsets,
+ SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
+ SubobjectCountMapTy &SubobjectCounts);
+
+ typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+
+ /// dump - dump the final overriders for a base subobject, and all its direct
+ /// and indirect base subobjects.
+ void dump(raw_ostream &Out, BaseSubobject Base,
+ VisitedVirtualBasesSetTy& VisitedVirtualBases);
+
+public:
+ FinalOverriders(const CXXRecordDecl *MostDerivedClass,
+ CharUnits MostDerivedClassOffset,
+ const CXXRecordDecl *LayoutClass);
+
+ /// getOverrider - Get the final overrider for the given method declaration in
+ /// the subobject with the given base offset.
+ OverriderInfo getOverrider(const CXXMethodDecl *MD,
+ CharUnits BaseOffset) const {
+ assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
+ "Did not find overrider!");
+
+ return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
+ }
+
+ /// dump - dump the final overriders.
+ void dump() {
+ VisitedVirtualBasesSetTy VisitedVirtualBases;
+ dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()),
+ VisitedVirtualBases);
+ }
+
+};
+
+#define DUMP_OVERRIDERS 0
+
+FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
+ CharUnits MostDerivedClassOffset,
+ const CXXRecordDecl *LayoutClass)
+ : MostDerivedClass(MostDerivedClass),
+ MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
+ Context(MostDerivedClass->getASTContext()),
+ MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
+
+ // Compute base offsets.
+ SubobjectOffsetMapTy SubobjectOffsets;
+ SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
+ SubobjectCountMapTy SubobjectCounts;
+ ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
+ /*IsVirtual=*/false,
+ MostDerivedClassOffset,
+ SubobjectOffsets, SubobjectLayoutClassOffsets,
+ SubobjectCounts);
+
+ // Get the the final overriders.
+ CXXFinalOverriderMap FinalOverriders;
+ MostDerivedClass->getFinalOverriders(FinalOverriders);
+
+ for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
+ E = FinalOverriders.end(); I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ const OverridingMethods& Methods = I->second;
+
+ for (OverridingMethods::const_iterator I = Methods.begin(),
+ E = Methods.end(); I != E; ++I) {
+ unsigned SubobjectNumber = I->first;
+ assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
+ SubobjectNumber)) &&
+ "Did not find subobject offset!");
+
+ CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(),
+ SubobjectNumber)];
+
+ assert(I->second.size() == 1 && "Final overrider is not unique!");
+ const UniqueVirtualMethod &Method = I->second.front();
+
+ const CXXRecordDecl *OverriderRD = Method.Method->getParent();
+ assert(SubobjectLayoutClassOffsets.count(
+ std::make_pair(OverriderRD, Method.Subobject))
+ && "Did not find subobject offset!");
+ CharUnits OverriderOffset =
+ SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
+ Method.Subobject)];
+
+ OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
+ assert(!Overrider.Method && "Overrider should not exist yet!");
+
+ Overrider.Offset = OverriderOffset;
+ Overrider.Method = Method.Method;
+ }
+ }
+
+#if DUMP_OVERRIDERS
+ // And dump them (for now).
+ dump();
+#endif
+}
+
+static BaseOffset ComputeBaseOffset(ASTContext &Context,
+ const CXXRecordDecl *DerivedRD,
+ const CXXBasePath &Path) {
+ CharUnits NonVirtualOffset = CharUnits::Zero();
+
+ unsigned NonVirtualStart = 0;
+ const CXXRecordDecl *VirtualBase = 0;
+
+ // First, look for the virtual base class.
+ for (unsigned I = 0, E = Path.size(); I != E; ++I) {
+ const CXXBasePathElement &Element = Path[I];
+
+ if (Element.Base->isVirtual()) {
+ // FIXME: Can we break when we find the first virtual base?
+ // (If we can't, can't we just iterate over the path in reverse order?)
+ NonVirtualStart = I + 1;
+ QualType VBaseType = Element.Base->getType();
+ VirtualBase =
+ cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
+ }
+ }
+
+ // Now compute the non-virtual offset.
+ for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
+ const CXXBasePathElement &Element = Path[I];
+
+ // Check the base class offset.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
+
+ const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
+ const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
+
+ NonVirtualOffset += Layout.getBaseClassOffset(Base);
+ }
+
+ // FIXME: This should probably use CharUnits or something. Maybe we should
+ // even change the base offsets in ASTRecordLayout to be specified in
+ // CharUnits.
+ return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset);
+
+}
+
+static BaseOffset ComputeBaseOffset(ASTContext &Context,
+ const CXXRecordDecl *BaseRD,
+ const CXXRecordDecl *DerivedRD) {
+ CXXBasePaths Paths(/*FindAmbiguities=*/false,
+ /*RecordPaths=*/true, /*DetectVirtual=*/false);
+
+ if (!const_cast<CXXRecordDecl *>(DerivedRD)->
+ isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
+ llvm_unreachable("Class must be derived from the passed in base class!");
+ }
+
+ return ComputeBaseOffset(Context, DerivedRD, Paths.front());
+}
+
+static BaseOffset
+ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
+ const CXXMethodDecl *DerivedMD,
+ const CXXMethodDecl *BaseMD) {
+ const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
+ const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
+
+ // Canonicalize the return types.
+ CanQualType CanDerivedReturnType =
+ Context.getCanonicalType(DerivedFT->getResultType());
+ CanQualType CanBaseReturnType =
+ Context.getCanonicalType(BaseFT->getResultType());
+
+ assert(CanDerivedReturnType->getTypeClass() ==
+ CanBaseReturnType->getTypeClass() &&
+ "Types must have same type class!");
+
+ if (CanDerivedReturnType == CanBaseReturnType) {
+ // No adjustment needed.
+ return BaseOffset();
+ }
+
+ if (isa<ReferenceType>(CanDerivedReturnType)) {
+ CanDerivedReturnType =
+ CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType();
+ CanBaseReturnType =
+ CanBaseReturnType->getAs<ReferenceType>()->getPointeeType();
+ } else if (isa<PointerType>(CanDerivedReturnType)) {
+ CanDerivedReturnType =
+ CanDerivedReturnType->getAs<PointerType>()->getPointeeType();
+ CanBaseReturnType =
+ CanBaseReturnType->getAs<PointerType>()->getPointeeType();
+ } else {
+ llvm_unreachable("Unexpected return type!");
+ }
+
+ // We need to compare unqualified types here; consider
+ // const T *Base::foo();
+ // T *Derived::foo();
+ if (CanDerivedReturnType.getUnqualifiedType() ==
+ CanBaseReturnType.getUnqualifiedType()) {
+ // No adjustment needed.
+ return BaseOffset();
+ }
+
+ const CXXRecordDecl *DerivedRD =
+ cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
+
+ const CXXRecordDecl *BaseRD =
+ cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
+
+ return ComputeBaseOffset(Context, BaseRD, DerivedRD);
+}
+
+void
+FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
+ CharUnits OffsetInLayoutClass,
+ SubobjectOffsetMapTy &SubobjectOffsets,
+ SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
+ SubobjectCountMapTy &SubobjectCounts) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ unsigned SubobjectNumber = 0;
+ if (!IsVirtual)
+ SubobjectNumber = ++SubobjectCounts[RD];
+
+ // Set up the subobject to offset mapping.
+ assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
+ && "Subobject offset already exists!");
+ assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
+ && "Subobject offset already exists!");
+
+ SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.getBaseOffset();
+ SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
+ OffsetInLayoutClass;
+
+ // Traverse our bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits BaseOffset;
+ CharUnits BaseOffsetInLayoutClass;
+ if (I->isVirtual()) {
+ // Check if we've visited this virtual base before.
+ if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
+ continue;
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+ BaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffset(BaseDecl);
+ } else {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ CharUnits Offset = Layout.getBaseClassOffset(BaseDecl);
+
+ BaseOffset = Base.getBaseOffset() + Offset;
+ BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
+ }
+
+ ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset),
+ I->isVirtual(), BaseOffsetInLayoutClass,
+ SubobjectOffsets, SubobjectLayoutClassOffsets,
+ SubobjectCounts);
+ }
+}
+
+void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
+ VisitedVirtualBasesSetTy &VisitedVirtualBases) {
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore bases that don't have any virtual member functions.
+ if (!BaseDecl->isPolymorphic())
+ continue;
+
+ CharUnits BaseOffset;
+ if (I->isVirtual()) {
+ if (!VisitedVirtualBases.insert(BaseDecl)) {
+ // We've visited this base before.
+ continue;
+ }
+
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+ } else {
+ BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset();
+ }
+
+ dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases);
+ }
+
+ Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", ";
+ Out << Base.getBaseOffset().getQuantity() << ")\n";
+
+ // Now dump the overriders for this base subobject.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *MD = *I;
+
+ if (!MD->isVirtual())
+ continue;
+
+ OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset());
+
+ Out << " " << MD->getQualifiedNameAsString() << " - (";
+ Out << Overrider.Method->getQualifiedNameAsString();
+ Out << ", " << ", " << Overrider.Offset.getQuantity() << ')';
+
+ BaseOffset Offset;
+ if (!Overrider.Method->isPure())
+ Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
+
+ if (!Offset.isEmpty()) {
+ Out << " [ret-adj: ";
+ if (Offset.VirtualBase)
+ Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, ";
+
+ Out << Offset.NonVirtualOffset.getQuantity() << " nv]";
+ }
+
+ Out << "\n";
+ }
+}
+
+/// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
+struct VCallOffsetMap {
+
+ typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
+
+ /// Offsets - Keeps track of methods and their offsets.
+ // FIXME: This should be a real map and not a vector.
+ SmallVector<MethodAndOffsetPairTy, 16> Offsets;
+
+ /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
+ /// can share the same vcall offset.
+ static bool MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS);
+
+public:
+ /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
+ /// add was successful, or false if there was already a member function with
+ /// the same signature in the map.
+ bool AddVCallOffset(const CXXMethodDecl *MD, CharUnits OffsetOffset);
+
+ /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
+ /// vtable address point) for the given virtual member function.
+ CharUnits getVCallOffsetOffset(const CXXMethodDecl *MD);
+
+ // empty - Return whether the offset map is empty or not.
+ bool empty() const { return Offsets.empty(); }
+};
+
+static bool HasSameVirtualSignature(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS) {
+ ASTContext &C = LHS->getASTContext(); // TODO: thread this down
+ CanQual<FunctionProtoType>
+ LT = C.getCanonicalType(LHS->getType()).getAs<FunctionProtoType>(),
+ RT = C.getCanonicalType(RHS->getType()).getAs<FunctionProtoType>();
+
+ // Fast-path matches in the canonical types.
+ if (LT == RT) return true;
+
+ // Force the signatures to match. We can't rely on the overrides
+ // list here because there isn't necessarily an inheritance
+ // relationship between the two methods.
+ if (LT.getQualifiers() != RT.getQualifiers() ||
+ LT->getNumArgs() != RT->getNumArgs())
+ return false;
+ for (unsigned I = 0, E = LT->getNumArgs(); I != E; ++I)
+ if (LT->getArgType(I) != RT->getArgType(I))
+ return false;
+ return true;
+}
+
+bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS) {
+ assert(LHS->isVirtual() && "LHS must be virtual!");
+ assert(RHS->isVirtual() && "LHS must be virtual!");
+
+ // A destructor can share a vcall offset with another destructor.
+ if (isa<CXXDestructorDecl>(LHS))
+ return isa<CXXDestructorDecl>(RHS);
+
+ // FIXME: We need to check more things here.
+
+ // The methods must have the same name.
+ DeclarationName LHSName = LHS->getDeclName();
+ DeclarationName RHSName = RHS->getDeclName();
+ if (LHSName != RHSName)
+ return false;
+
+ // And the same signatures.
+ return HasSameVirtualSignature(LHS, RHS);
+}
+
+bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
+ CharUnits OffsetOffset) {
+ // Check if we can reuse an offset.
+ for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
+ if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+ return false;
+ }
+
+ // Add the offset.
+ Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
+ return true;
+}
+
+CharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
+ // Look for an offset.
+ for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
+ if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+ return Offsets[I].second;
+ }
+
+ llvm_unreachable("Should always find a vcall offset offset!");
+}
+
+/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
+class VCallAndVBaseOffsetBuilder {
+public:
+ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
+ VBaseOffsetOffsetsMapTy;
+
+private:
+ /// MostDerivedClass - The most derived class for which we're building vcall
+ /// and vbase offsets.
+ const CXXRecordDecl *MostDerivedClass;
+
+ /// LayoutClass - The class we're using for layout information. Will be
+ /// different than the most derived class if we're building a construction
+ /// vtable.
+ const CXXRecordDecl *LayoutClass;
+
+ /// Context - The ASTContext which we will use for layout information.
+ ASTContext &Context;
+
+ /// Components - vcall and vbase offset components
+ typedef SmallVector<VTableComponent, 64> VTableComponentVectorTy;
+ VTableComponentVectorTy Components;
+
+ /// VisitedVirtualBases - Visited virtual bases.
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
+
+ /// VCallOffsets - Keeps track of vcall offsets.
+ VCallOffsetMap VCallOffsets;
+
+
+ /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
+ /// relative to the address point.
+ VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
+
+ /// FinalOverriders - The final overriders of the most derived class.
+ /// (Can be null when we're not building a vtable of the most derived class).
+ const FinalOverriders *Overriders;
+
+ /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
+ /// given base subobject.
+ void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
+ CharUnits RealBaseOffset);
+
+ /// AddVCallOffsets - Add vcall offsets for the given base subobject.
+ void AddVCallOffsets(BaseSubobject Base, CharUnits VBaseOffset);
+
+ /// AddVBaseOffsets - Add vbase offsets for the given class.
+ void AddVBaseOffsets(const CXXRecordDecl *Base,
+ CharUnits OffsetInLayoutClass);
+
+ /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
+ /// chars, relative to the vtable address point.
+ CharUnits getCurrentOffsetOffset() const;
+
+public:
+ VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
+ const CXXRecordDecl *LayoutClass,
+ const FinalOverriders *Overriders,
+ BaseSubobject Base, bool BaseIsVirtual,
+ CharUnits OffsetInLayoutClass)
+ : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
+ Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
+
+ // Add vcall and vbase offsets.
+ AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
+ }
+
+ /// Methods for iterating over the components.
+ typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
+ const_iterator components_begin() const { return Components.rbegin(); }
+ const_iterator components_end() const { return Components.rend(); }
+
+ const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
+ const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
+ return VBaseOffsetOffsets;
+ }
+};
+
+void
+VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
+ bool BaseIsVirtual,
+ CharUnits RealBaseOffset) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
+
+ // Itanium C++ ABI 2.5.2:
+ // ..in classes sharing a virtual table with a primary base class, the vcall
+ // and vbase offsets added by the derived class all come before the vcall
+ // and vbase offsets required by the base class, so that the latter may be
+ // laid out as required by the base class without regard to additions from
+ // the derived class(es).
+
+ // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
+ // emit them for the primary base first).
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+ bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
+
+ CharUnits PrimaryBaseOffset;
+
+ // Get the base offset of the primary base.
+ if (PrimaryBaseIsVirtual) {
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ PrimaryBaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+ } else {
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ PrimaryBaseOffset = Base.getBaseOffset();
+ }
+
+ AddVCallAndVBaseOffsets(
+ BaseSubobject(PrimaryBase,PrimaryBaseOffset),
+ PrimaryBaseIsVirtual, RealBaseOffset);
+ }
+
+ AddVBaseOffsets(Base.getBase(), RealBaseOffset);
+
+ // We only want to add vcall offsets for virtual bases.
+ if (BaseIsVirtual)
+ AddVCallOffsets(Base, RealBaseOffset);
+}
+
+CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
+ // OffsetIndex is the index of this vcall or vbase offset, relative to the
+ // vtable address point. (We subtract 3 to account for the information just
+ // above the address point, the RTTI info, the offset to top, and the
+ // vcall offset itself).
+ int64_t OffsetIndex = -(int64_t)(3 + Components.size());
+
+ CharUnits PointerWidth =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+ CharUnits OffsetOffset = PointerWidth * OffsetIndex;
+ return OffsetOffset;
+}
+
+void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
+ CharUnits VBaseOffset) {
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ // Handle the primary base first.
+ // We only want to add vcall offsets if the base is non-virtual; a virtual
+ // primary base will have its vcall and vbase offsets emitted already.
+ if (PrimaryBase && !Layout.isPrimaryBaseVirtual()) {
+ // Get the base offset of the primary base.
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
+ VBaseOffset);
+ }
+
+ // Add the vcall offsets.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *MD = *I;
+
+ if (!MD->isVirtual())
+ continue;
+
+ CharUnits OffsetOffset = getCurrentOffsetOffset();
+
+ // Don't add a vcall offset if we already have one for this member function
+ // signature.
+ if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
+ continue;
+
+ CharUnits Offset = CharUnits::Zero();
+
+ if (Overriders) {
+ // Get the final overrider.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders->getOverrider(MD, Base.getBaseOffset());
+
+ /// The vcall offset is the offset from the virtual base to the object
+ /// where the function was overridden.
+ Offset = Overrider.Offset - VBaseOffset;
+ }
+
+ Components.push_back(
+ VTableComponent::MakeVCallOffset(Offset));
+ }
+
+ // And iterate over all non-virtual bases (ignoring the primary base).
+ 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());
+ if (BaseDecl == PrimaryBase)
+ continue;
+
+ // Get the base offset of this base.
+ CharUnits BaseOffset = Base.getBaseOffset() +
+ Layout.getBaseClassOffset(BaseDecl);
+
+ AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset),
+ VBaseOffset);
+ }
+}
+
+void
+VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
+ CharUnits OffsetInLayoutClass) {
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ // Add vbase offsets.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this is a virtual base that we haven't visited before.
+ if (I->isVirtual() && VisitedVirtualBases.insert(BaseDecl)) {
+ CharUnits Offset =
+ LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass;
+
+ // Add the vbase offset offset.
+ assert(!VBaseOffsetOffsets.count(BaseDecl) &&
+ "vbase offset offset already exists!");
+
+ CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
+ VBaseOffsetOffsets.insert(
+ std::make_pair(BaseDecl, VBaseOffsetOffset));
+
+ Components.push_back(
+ VTableComponent::MakeVBaseOffset(Offset));
+ }
+
+ // Check the base class looking for more vbase offsets.
+ AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
+ }
+}
+
+/// VTableBuilder - Class for building vtable layout information.
+class VTableBuilder {
+public:
+ /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
+ /// primary bases.
+ typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
+ PrimaryBasesSetVectorTy;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
+ VBaseOffsetOffsetsMapTy;
+
+ typedef llvm::DenseMap<BaseSubobject, uint64_t>
+ AddressPointsMapTy;
+
+private:
+ /// VTables - Global vtable information.
+ VTableContext &VTables;
+
+ /// MostDerivedClass - The most derived class for which we're building this
+ /// vtable.
+ const CXXRecordDecl *MostDerivedClass;
+
+ /// MostDerivedClassOffset - If we're building a construction vtable, this
+ /// holds the offset from the layout class to the most derived class.
+ const CharUnits MostDerivedClassOffset;
+
+ /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
+ /// base. (This only makes sense when building a construction vtable).
+ bool MostDerivedClassIsVirtual;
+
+ /// LayoutClass - The class we're using for layout information. Will be
+ /// different than the most derived class if we're building a construction
+ /// vtable.
+ const CXXRecordDecl *LayoutClass;
+
+ /// Context - The ASTContext which we will use for layout information.
+ ASTContext &Context;
+
+ /// FinalOverriders - The final overriders of the most derived class.
+ const FinalOverriders Overriders;
+
+ /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
+ /// bases in this vtable.
+ llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
+
+ /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
+ /// the most derived class.
+ VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
+
+ /// Components - The components of the vtable being built.
+ SmallVector<VTableComponent, 64> Components;
+
+ /// AddressPoints - Address points for the vtable being built.
+ AddressPointsMapTy AddressPoints;
+
+ /// MethodInfo - Contains information about a method in a vtable.
+ /// (Used for computing 'this' pointer adjustment thunks.
+ struct MethodInfo {
+ /// BaseOffset - The base offset of this method.
+ const CharUnits BaseOffset;
+
+ /// BaseOffsetInLayoutClass - The base offset in the layout class of this
+ /// method.
+ const CharUnits BaseOffsetInLayoutClass;
+
+ /// VTableIndex - The index in the vtable that this method has.
+ /// (For destructors, this is the index of the complete destructor).
+ const uint64_t VTableIndex;
+
+ MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass,
+ uint64_t VTableIndex)
+ : BaseOffset(BaseOffset),
+ BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
+ VTableIndex(VTableIndex) { }
+
+ MethodInfo()
+ : BaseOffset(CharUnits::Zero()),
+ BaseOffsetInLayoutClass(CharUnits::Zero()),
+ VTableIndex(0) { }
+ };
+
+ typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
+
+ /// MethodInfoMap - The information for all methods in the vtable we're
+ /// currently building.
+ MethodInfoMapTy MethodInfoMap;
+
+ typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
+
+ /// VTableThunks - The thunks by vtable index in the vtable currently being
+ /// built.
+ VTableThunksMapTy VTableThunks;
+
+ typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
+ typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
+
+ /// Thunks - A map that contains all the thunks needed for all methods in the
+ /// most derived class for which the vtable is currently being built.
+ ThunksMapTy Thunks;
+
+ /// AddThunk - Add a thunk for the given method.
+ void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk);
+
+ /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
+ /// part of the vtable we're currently building.
+ void ComputeThisAdjustments();
+
+ typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+
+ /// PrimaryVirtualBases - All known virtual bases who are a primary base of
+ /// some other base.
+ VisitedVirtualBasesSetTy PrimaryVirtualBases;
+
+ /// ComputeReturnAdjustment - Compute the return adjustment given a return
+ /// adjustment base offset.
+ ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset);
+
+ /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
+ /// the 'this' pointer from the base subobject to the derived subobject.
+ BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
+ BaseSubobject Derived) const;
+
+ /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
+ /// given virtual member function, its offset in the layout class and its
+ /// final overrider.
+ ThisAdjustment
+ ComputeThisAdjustment(const CXXMethodDecl *MD,
+ CharUnits BaseOffsetInLayoutClass,
+ FinalOverriders::OverriderInfo Overrider);
+
+ /// AddMethod - Add a single virtual member function to the vtable
+ /// components vector.
+ void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
+
+ /// IsOverriderUsed - Returns whether the overrider will ever be used in this
+ /// part of the vtable.
+ ///
+ /// Itanium C++ ABI 2.5.2:
+ ///
+ /// struct A { virtual void f(); };
+ /// struct B : virtual public A { int i; };
+ /// struct C : virtual public A { int j; };
+ /// struct D : public B, public C {};
+ ///
+ /// When B and C are declared, A is a primary base in each case, so although
+ /// vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
+ /// adjustment is required and no thunk is generated. However, inside D
+ /// objects, A is no longer a primary base of C, so if we allowed calls to
+ /// C::f() to use the copy of A's vtable in the C subobject, we would need
+ /// to adjust this from C* to B::A*, which would require a third-party
+ /// thunk. Since we require that a call to C::f() first convert to A*,
+ /// C-in-D's copy of A's vtable is never referenced, so this is not
+ /// necessary.
+ bool IsOverriderUsed(const CXXMethodDecl *Overrider,
+ CharUnits BaseOffsetInLayoutClass,
+ const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
+ CharUnits FirstBaseOffsetInLayoutClass) const;
+
+
+ /// AddMethods - Add the methods of this base subobject and all its
+ /// primary bases to the vtable components vector.
+ void AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
+ const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
+ CharUnits FirstBaseOffsetInLayoutClass,
+ PrimaryBasesSetVectorTy &PrimaryBases);
+
+ // LayoutVTable - Layout the vtable for the given base class, including its
+ // secondary vtables and any vtables for virtual bases.
+ void LayoutVTable();
+
+ /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
+ /// given base subobject, as well as all its secondary vtables.
+ ///
+ /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
+ /// or a direct or indirect base of a virtual base.
+ ///
+ /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
+ /// in the layout class.
+ void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ bool BaseIsVirtualInLayoutClass,
+ CharUnits OffsetInLayoutClass);
+
+ /// LayoutSecondaryVTables - Layout the secondary vtables for the given base
+ /// subobject.
+ ///
+ /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
+ /// or a direct or indirect base of a virtual base.
+ void LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual,
+ CharUnits OffsetInLayoutClass);
+
+ /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
+ /// class hierarchy.
+ void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ CharUnits OffsetInLayoutClass,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
+ /// given base (excluding any primary bases).
+ void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// isBuildingConstructionVTable - Return whether this vtable builder is
+ /// building a construction vtable.
+ bool isBuildingConstructorVTable() const {
+ return MostDerivedClass != LayoutClass;
+ }
+
+public:
+ VTableBuilder(VTableContext &VTables, const CXXRecordDecl *MostDerivedClass,
+ CharUnits MostDerivedClassOffset,
+ bool MostDerivedClassIsVirtual, const
+ CXXRecordDecl *LayoutClass)
+ : VTables(VTables), MostDerivedClass(MostDerivedClass),
+ MostDerivedClassOffset(MostDerivedClassOffset),
+ MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
+ LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
+ Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
+
+ LayoutVTable();
+
+ if (Context.getLangOptions().DumpVTableLayouts)
+ dumpLayout(llvm::errs());
+ }
+
+ uint64_t getNumThunks() const {
+ return Thunks.size();
+ }
+
+ ThunksMapTy::const_iterator thunks_begin() const {
+ return Thunks.begin();
+ }
+
+ ThunksMapTy::const_iterator thunks_end() const {
+ return Thunks.end();
+ }
+
+ const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
+ return VBaseOffsetOffsets;
+ }
+
+ const AddressPointsMapTy &getAddressPoints() const {
+ return AddressPoints;
+ }
+
+ /// getNumVTableComponents - Return the number of components in the vtable
+ /// currently built.
+ uint64_t getNumVTableComponents() const {
+ return Components.size();
+ }
+
+ const VTableComponent *vtable_component_begin() const {
+ return Components.begin();
+ }
+
+ const VTableComponent *vtable_component_end() const {
+ return Components.end();
+ }
+
+ AddressPointsMapTy::const_iterator address_points_begin() const {
+ return AddressPoints.begin();
+ }
+
+ AddressPointsMapTy::const_iterator address_points_end() const {
+ return AddressPoints.end();
+ }
+
+ VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
+ return VTableThunks.begin();
+ }
+
+ VTableThunksMapTy::const_iterator vtable_thunks_end() const {
+ return VTableThunks.end();
+ }
+
+ /// dumpLayout - Dump the vtable layout.
+ void dumpLayout(raw_ostream&);
+};
+
+void VTableBuilder::AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) {
+ assert(!isBuildingConstructorVTable() &&
+ "Can't add thunks for construction vtable");
+
+ SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
+
+ // Check if we have this thunk already.
+ if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
+ ThunksVector.end())
+ return;
+
+ ThunksVector.push_back(Thunk);
+}
+
+typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
+
+/// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
+/// the overridden methods that the function decl overrides.
+static void
+ComputeAllOverriddenMethods(const CXXMethodDecl *MD,
+ OverriddenMethodsSetTy& OverriddenMethods) {
+ assert(MD->isVirtual() && "Method is not virtual!");
+
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods(); I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+
+ OverriddenMethods.insert(OverriddenMD);
+
+ ComputeAllOverriddenMethods(OverriddenMD, OverriddenMethods);
+ }
+}
+
+void VTableBuilder::ComputeThisAdjustments() {
+ // Now go through the method info map and see if any of the methods need
+ // 'this' pointer adjustments.
+ for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
+ E = MethodInfoMap.end(); I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ const MethodInfo &MethodInfo = I->second;
+
+ // Ignore adjustments for unused function pointers.
+ uint64_t VTableIndex = MethodInfo.VTableIndex;
+ if (Components[VTableIndex].getKind() ==
+ VTableComponent::CK_UnusedFunctionPointer)
+ continue;
+
+ // Get the final overrider for this method.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders.getOverrider(MD, MethodInfo.BaseOffset);
+
+ // Check if we need an adjustment at all.
+ if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
+ // When a return thunk is needed by a derived class that overrides a
+ // virtual base, gcc uses a virtual 'this' adjustment as well.
+ // While the thunk itself might be needed by vtables in subclasses or
+ // in construction vtables, there doesn't seem to be a reason for using
+ // the thunk in this vtable. Still, we do so to match gcc.
+ if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
+ continue;
+ }
+
+ ThisAdjustment ThisAdjustment =
+ ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
+
+ if (ThisAdjustment.isEmpty())
+ continue;
+
+ // Add it.
+ VTableThunks[VTableIndex].This = ThisAdjustment;
+
+ if (isa<CXXDestructorDecl>(MD)) {
+ // Add an adjustment for the deleting destructor as well.
+ VTableThunks[VTableIndex + 1].This = ThisAdjustment;
+ }
+ }
+
+ /// Clear the method info map.
+ MethodInfoMap.clear();
+
+ if (isBuildingConstructorVTable()) {
+ // We don't need to store thunk information for construction vtables.
+ return;
+ }
+
+ for (VTableThunksMapTy::const_iterator I = VTableThunks.begin(),
+ E = VTableThunks.end(); I != E; ++I) {
+ const VTableComponent &Component = Components[I->first];
+ const ThunkInfo &Thunk = I->second;
+ const CXXMethodDecl *MD;
+
+ switch (Component.getKind()) {
+ default:
+ llvm_unreachable("Unexpected vtable component kind!");
+ case VTableComponent::CK_FunctionPointer:
+ MD = Component.getFunctionDecl();
+ break;
+ case VTableComponent::CK_CompleteDtorPointer:
+ MD = Component.getDestructorDecl();
+ break;
+ case VTableComponent::CK_DeletingDtorPointer:
+ // We've already added the thunk when we saw the complete dtor pointer.
+ continue;
+ }
+
+ if (MD->getParent() == MostDerivedClass)
+ AddThunk(MD, Thunk);
+ }
+}
+
+ReturnAdjustment VTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
+ ReturnAdjustment Adjustment;
+
+ if (!Offset.isEmpty()) {
+ if (Offset.VirtualBase) {
+ // Get the virtual base offset offset.
+ if (Offset.DerivedClass == MostDerivedClass) {
+ // We can get the offset offset directly from our map.
+ Adjustment.VBaseOffsetOffset =
+ VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
+ } else {
+ Adjustment.VBaseOffsetOffset =
+ VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
+ Offset.VirtualBase).getQuantity();
+ }
+ }
+
+ Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
+ }
+
+ return Adjustment;
+}
+
+BaseOffset
+VTableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
+ BaseSubobject Derived) const {
+ const CXXRecordDecl *BaseRD = Base.getBase();
+ const CXXRecordDecl *DerivedRD = Derived.getBase();
+
+ CXXBasePaths Paths(/*FindAmbiguities=*/true,
+ /*RecordPaths=*/true, /*DetectVirtual=*/true);
+
+ if (!const_cast<CXXRecordDecl *>(DerivedRD)->
+ isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
+ llvm_unreachable("Class must be derived from the passed in base class!");
+ }
+
+ // We have to go through all the paths, and see which one leads us to the
+ // right base subobject.
+ for (CXXBasePaths::const_paths_iterator I = Paths.begin(), E = Paths.end();
+ I != E; ++I) {
+ BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I);
+
+ CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
+
+ if (Offset.VirtualBase) {
+ // If we have a virtual base class, the non-virtual offset is relative
+ // to the virtual base class offset.
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ /// Get the virtual base offset, relative to the most derived class
+ /// layout.
+ OffsetToBaseSubobject +=
+ LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
+ } else {
+ // Otherwise, the non-virtual offset is relative to the derived class
+ // offset.
+ OffsetToBaseSubobject += Derived.getBaseOffset();
+ }
+
+ // Check if this path gives us the right base subobject.
+ if (OffsetToBaseSubobject == Base.getBaseOffset()) {
+ // Since we're going from the base class _to_ the derived class, we'll
+ // invert the non-virtual offset here.
+ Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
+ return Offset;
+ }
+ }
+
+ return BaseOffset();
+}
+
+ThisAdjustment
+VTableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
+ CharUnits BaseOffsetInLayoutClass,
+ FinalOverriders::OverriderInfo Overrider) {
+ // Ignore adjustments for pure virtual member functions.
+ if (Overrider.Method->isPure())
+ return ThisAdjustment();
+
+ BaseSubobject OverriddenBaseSubobject(MD->getParent(),
+ BaseOffsetInLayoutClass);
+
+ BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
+ Overrider.Offset);
+
+ // Compute the adjustment offset.
+ BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
+ OverriderBaseSubobject);
+ if (Offset.isEmpty())
+ return ThisAdjustment();
+
+ ThisAdjustment Adjustment;
+
+ if (Offset.VirtualBase) {
+ // Get the vcall offset map for this virtual base.
+ VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
+
+ if (VCallOffsets.empty()) {
+ // We don't have vcall offsets for this virtual base, go ahead and
+ // build them.
+ VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
+ /*FinalOverriders=*/0,
+ BaseSubobject(Offset.VirtualBase,
+ CharUnits::Zero()),
+ /*BaseIsVirtual=*/true,
+ /*OffsetInLayoutClass=*/
+ CharUnits::Zero());
+
+ VCallOffsets = Builder.getVCallOffsets();
+ }
+
+ Adjustment.VCallOffsetOffset =
+ VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
+ }
+
+ // Set the non-virtual part of the adjustment.
+ Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity();
+
+ return Adjustment;
+}
+
+void
+VTableBuilder::AddMethod(const CXXMethodDecl *MD,
+ ReturnAdjustment ReturnAdjustment) {
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ assert(ReturnAdjustment.isEmpty() &&
+ "Destructor can't have return adjustment!");
+
+ // Add both the complete destructor and the deleting destructor.
+ Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+ Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+ } else {
+ // Add the return adjustment if necessary.
+ if (!ReturnAdjustment.isEmpty())
+ VTableThunks[Components.size()].Return = ReturnAdjustment;
+
+ // Add the function.
+ Components.push_back(VTableComponent::MakeFunction(MD));
+ }
+}
+
+/// OverridesIndirectMethodInBase - Return whether the given member function
+/// overrides any methods in the set of given bases.
+/// Unlike OverridesMethodInBase, this checks "overriders of overriders".
+/// For example, if we have:
+///
+/// struct A { virtual void f(); }
+/// struct B : A { virtual void f(); }
+/// struct C : B { virtual void f(); }
+///
+/// OverridesIndirectMethodInBase will return true if given C::f as the method
+/// and { A } as the set of bases.
+static bool
+OverridesIndirectMethodInBases(const CXXMethodDecl *MD,
+ VTableBuilder::PrimaryBasesSetVectorTy &Bases) {
+ if (Bases.count(MD->getParent()))
+ return true;
+
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods(); I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+
+ // Check "indirect overriders".
+ if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
+ return true;
+ }
+
+ return false;
+}
+
+bool
+VTableBuilder::IsOverriderUsed(const CXXMethodDecl *Overrider,
+ CharUnits BaseOffsetInLayoutClass,
+ const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
+ CharUnits FirstBaseOffsetInLayoutClass) const {
+ // If the base and the first base in the primary base chain have the same
+ // offsets, then this overrider will be used.
+ if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
+ return true;
+
+ // We know now that Base (or a direct or indirect base of it) is a primary
+ // base in part of the class hierarchy, but not a primary base in the most
+ // derived class.
+
+ // If the overrider is the first base in the primary base chain, we know
+ // that the overrider will be used.
+ if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
+ return true;
+
+ VTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
+
+ const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain;
+ PrimaryBases.insert(RD);
+
+ // Now traverse the base chain, starting with the first base, until we find
+ // the base that is no longer a primary base.
+ while (true) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ if (!PrimaryBase)
+ break;
+
+ if (Layout.isPrimaryBaseVirtual()) {
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should always be at offset 0!");
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ // Now check if this is the primary base that is not a primary base in the
+ // most derived class.
+ if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
+ FirstBaseOffsetInLayoutClass) {
+ // We found it, stop walking the chain.
+ break;
+ }
+ } else {
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should always be at offset 0!");
+ }
+
+ if (!PrimaryBases.insert(PrimaryBase))
+ llvm_unreachable("Found a duplicate primary base!");
+
+ RD = PrimaryBase;
+ }
+
+ // If the final overrider is an override of one of the primary bases,
+ // then we know that it will be used.
+ return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
+}
+
+/// FindNearestOverriddenMethod - Given a method, returns the overridden method
+/// from the nearest base. Returns null if no method was found.
+static const CXXMethodDecl *
+FindNearestOverriddenMethod(const CXXMethodDecl *MD,
+ VTableBuilder::PrimaryBasesSetVectorTy &Bases) {
+ OverriddenMethodsSetTy OverriddenMethods;
+ ComputeAllOverriddenMethods(MD, OverriddenMethods);
+
+ for (int I = Bases.size(), E = 0; I != E; --I) {
+ const CXXRecordDecl *PrimaryBase = Bases[I - 1];
+
+ // Now check the overriden methods.
+ for (OverriddenMethodsSetTy::const_iterator I = OverriddenMethods.begin(),
+ E = OverriddenMethods.end(); I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+
+ // We found our overridden method.
+ if (OverriddenMD->getParent() == PrimaryBase)
+ return OverriddenMD;
+ }
+ }
+
+ return 0;
+}
+
+void
+VTableBuilder::AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass,
+ const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
+ CharUnits FirstBaseOffsetInLayoutClass,
+ PrimaryBasesSetVectorTy &PrimaryBases) {
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+ CharUnits PrimaryBaseOffset;
+ CharUnits PrimaryBaseOffsetInLayoutClass;
+ if (Layout.isPrimaryBaseVirtual()) {
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ PrimaryBaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ PrimaryBaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
+ } else {
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ PrimaryBaseOffset = Base.getBaseOffset();
+ PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
+ }
+
+ AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
+ PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
+ FirstBaseOffsetInLayoutClass, PrimaryBases);
+
+ if (!PrimaryBases.insert(PrimaryBase))
+ llvm_unreachable("Found a duplicate primary base!");
+ }
+
+ // Now go through all virtual member functions and add them.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *MD = *I;
+
+ if (!MD->isVirtual())
+ continue;
+
+ // Get the final overrider.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders.getOverrider(MD, Base.getBaseOffset());
+
+ // Check if this virtual member function overrides a method in a primary
+ // base. If this is the case, and the return type doesn't require adjustment
+ // then we can just use the member function from the primary base.
+ if (const CXXMethodDecl *OverriddenMD =
+ FindNearestOverriddenMethod(MD, PrimaryBases)) {
+ if (ComputeReturnAdjustmentBaseOffset(Context, MD,
+ OverriddenMD).isEmpty()) {
+ // Replace the method info of the overridden method with our own
+ // method.
+ assert(MethodInfoMap.count(OverriddenMD) &&
+ "Did not find the overridden method!");
+ MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
+
+ MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
+ OverriddenMethodInfo.VTableIndex);
+
+ assert(!MethodInfoMap.count(MD) &&
+ "Should not have method info for this method yet!");
+
+ MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
+ MethodInfoMap.erase(OverriddenMD);
+
+ // If the overridden method exists in a virtual base class or a direct
+ // or indirect base class of a virtual base class, we need to emit a
+ // thunk if we ever have a class hierarchy where the base class is not
+ // a primary base in the complete object.
+ if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
+ // Compute the this adjustment.
+ ThisAdjustment ThisAdjustment =
+ ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
+ Overrider);
+
+ if (ThisAdjustment.VCallOffsetOffset &&
+ Overrider.Method->getParent() == MostDerivedClass) {
+
+ // There's no return adjustment from OverriddenMD and MD,
+ // but that doesn't mean there isn't one between MD and
+ // the final overrider.
+ BaseOffset ReturnAdjustmentOffset =
+ ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
+ ReturnAdjustment ReturnAdjustment =
+ ComputeReturnAdjustment(ReturnAdjustmentOffset);
+
+ // This is a virtual thunk for the most derived class, add it.
+ AddThunk(Overrider.Method,
+ ThunkInfo(ThisAdjustment, ReturnAdjustment));
+ }
+ }
+
+ continue;
+ }
+ }
+
+ // Insert the method info for this method.
+ MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
+ Components.size());
+
+ assert(!MethodInfoMap.count(MD) &&
+ "Should not have method info for this method yet!");
+ MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
+
+ // Check if this overrider is going to be used.
+ const CXXMethodDecl *OverriderMD = Overrider.Method;
+ if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
+ FirstBaseInPrimaryBaseChain,
+ FirstBaseOffsetInLayoutClass)) {
+ Components.push_back(VTableComponent::MakeUnusedFunction(OverriderMD));
+ continue;
+ }
+
+ // Check if this overrider needs a return adjustment.
+ // We don't want to do this for pure virtual member functions.
+ BaseOffset ReturnAdjustmentOffset;
+ if (!OverriderMD->isPure()) {
+ ReturnAdjustmentOffset =
+ ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
+ }
+
+ ReturnAdjustment ReturnAdjustment =
+ ComputeReturnAdjustment(ReturnAdjustmentOffset);
+
+ AddMethod(Overrider.Method, ReturnAdjustment);
+ }
+}
+
+void VTableBuilder::LayoutVTable() {
+ LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass,
+ CharUnits::Zero()),
+ /*BaseIsMorallyVirtual=*/false,
+ MostDerivedClassIsVirtual,
+ MostDerivedClassOffset);
+
+ VisitedVirtualBasesSetTy VBases;
+
+ // Determine the primary virtual bases.
+ DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
+ VBases);
+ VBases.clear();
+
+ LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
+
+ // -fapple-kext adds an extra entry at end of vtbl.
+ bool IsAppleKext = Context.getLangOptions().AppleKext;
+ if (IsAppleKext)
+ Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero()));
+}
+
+void
+VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ bool BaseIsVirtualInLayoutClass,
+ CharUnits OffsetInLayoutClass) {
+ assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
+
+ // Add vcall and vbase offsets for this vtable.
+ VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
+ Base, BaseIsVirtualInLayoutClass,
+ OffsetInLayoutClass);
+ Components.append(Builder.components_begin(), Builder.components_end());
+
+ // Check if we need to add these vcall offsets.
+ if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
+ VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()];
+
+ if (VCallOffsets.empty())
+ VCallOffsets = Builder.getVCallOffsets();
+ }
+
+ // If we're laying out the most derived class we want to keep track of the
+ // virtual base class offset offsets.
+ if (Base.getBase() == MostDerivedClass)
+ VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
+
+ // Add the offset to top.
+ CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
+ Components.push_back(
+ VTableComponent::MakeOffsetToTop(OffsetToTop));
+
+ // Next, add the RTTI.
+ Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
+
+ uint64_t AddressPoint = Components.size();
+
+ // Now go through all virtual member functions and add them.
+ PrimaryBasesSetVectorTy PrimaryBases;
+ AddMethods(Base, OffsetInLayoutClass,
+ Base.getBase(), OffsetInLayoutClass,
+ PrimaryBases);
+
+ // Compute 'this' pointer adjustments.
+ ComputeThisAdjustments();
+
+ // Add all address points.
+ const CXXRecordDecl *RD = Base.getBase();
+ while (true) {
+ AddressPoints.insert(std::make_pair(
+ BaseSubobject(RD, OffsetInLayoutClass),
+ AddressPoint));
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ if (!PrimaryBase)
+ break;
+
+ if (Layout.isPrimaryBaseVirtual()) {
+ // Check if this virtual primary base is a primary base in the layout
+ // class. If it's not, we don't want to add it.
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
+ OffsetInLayoutClass) {
+ // We don't want to add this class (or any of its primary bases).
+ break;
+ }
+ }
+
+ RD = PrimaryBase;
+ }
+
+ // Layout secondary vtables.
+ LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
+}
+
+void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ CharUnits OffsetInLayoutClass) {
+ // Itanium C++ ABI 2.5.2:
+ // Following the primary virtual table of a derived class are secondary
+ // virtual tables for each of its proper base classes, except any primary
+ // base(s) with which it shares its primary virtual table.
+
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ // Ignore virtual bases, we'll emit them later.
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore bases that don't have a vtable.
+ if (!BaseDecl->isDynamicClass())
+ continue;
+
+ if (isBuildingConstructorVTable()) {
+ // Itanium C++ ABI 2.6.4:
+ // Some of the base class subobjects may not need construction virtual
+ // tables, which will therefore not be present in the construction
+ // virtual table group, even though the subobject virtual tables are
+ // present in the main virtual table group for the complete object.
+ if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
+ continue;
+ }
+
+ // Get the base offset of this base.
+ CharUnits RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
+ CharUnits BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
+
+ CharUnits BaseOffsetInLayoutClass =
+ OffsetInLayoutClass + RelativeBaseOffset;
+
+ // Don't emit a secondary vtable for a primary base. We might however want
+ // to emit secondary vtables for other bases of this base.
+ if (BaseDecl == PrimaryBase) {
+ LayoutSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
+ BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
+ continue;
+ }
+
+ // Layout the primary vtable (and any secondary vtables) for this base.
+ LayoutPrimaryAndSecondaryVTables(
+ BaseSubobject(BaseDecl, BaseOffset),
+ BaseIsMorallyVirtual,
+ /*BaseIsVirtualInLayoutClass=*/false,
+ BaseOffsetInLayoutClass);
+ }
+}
+
+void
+VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ CharUnits OffsetInLayoutClass,
+ VisitedVirtualBasesSetTy &VBases) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Check if this base has a primary base.
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+
+ // Check if it's virtual.
+ if (Layout.isPrimaryBaseVirtual()) {
+ bool IsPrimaryVirtualBase = true;
+
+ if (isBuildingConstructorVTable()) {
+ // Check if the base is actually a primary base in the class we use for
+ // layout.
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ CharUnits PrimaryBaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
+
+ // We know that the base is not a primary base in the layout class if
+ // the base offsets are different.
+ if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
+ IsPrimaryVirtualBase = false;
+ }
+
+ if (IsPrimaryVirtualBase)
+ PrimaryVirtualBases.insert(PrimaryBase);
+ }
+ }
+
+ // Traverse bases, looking for more primary virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits BaseOffsetInLayoutClass;
+
+ if (I->isVirtual()) {
+ if (!VBases.insert(BaseDecl))
+ continue;
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ BaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffset(BaseDecl);
+ } else {
+ BaseOffsetInLayoutClass =
+ OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl);
+ }
+
+ DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
+ }
+}
+
+void
+VTableBuilder::LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases) {
+ // Itanium C++ ABI 2.5.2:
+ // Then come the virtual base virtual tables, also in inheritance graph
+ // order, and again excluding primary bases (which share virtual tables with
+ // the classes for which they are primary).
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this base needs a vtable. (If it's virtual, not a primary base
+ // of some other class, and we haven't visited it before).
+ if (I->isVirtual() && BaseDecl->isDynamicClass() &&
+ !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) {
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+ CharUnits BaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+ CharUnits BaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffset(BaseDecl);
+
+ LayoutPrimaryAndSecondaryVTables(
+ BaseSubobject(BaseDecl, BaseOffset),
+ /*BaseIsMorallyVirtual=*/true,
+ /*BaseIsVirtualInLayoutClass=*/true,
+ BaseOffsetInLayoutClass);
+ }
+
+ // We only need to check the base for virtual base vtables if it actually
+ // has virtual bases.
+ if (BaseDecl->getNumVBases())
+ LayoutVTablesForVirtualBases(BaseDecl, VBases);
+ }
+}
+
+/// dumpLayout - Dump the vtable layout.
+void VTableBuilder::dumpLayout(raw_ostream& Out) {
+
+ if (isBuildingConstructorVTable()) {
+ Out << "Construction vtable for ('";
+ Out << MostDerivedClass->getQualifiedNameAsString() << "', ";
+ Out << MostDerivedClassOffset.getQuantity() << ") in '";
+ Out << LayoutClass->getQualifiedNameAsString();
+ } else {
+ Out << "Vtable for '";
+ Out << MostDerivedClass->getQualifiedNameAsString();
+ }
+ Out << "' (" << Components.size() << " entries).\n";
+
+ // Iterate through the address points and insert them into a new map where
+ // they are keyed by the index and not the base object.
+ // Since an address point can be shared by multiple subobjects, we use an
+ // STL multimap.
+ std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
+ for (AddressPointsMapTy::const_iterator I = AddressPoints.begin(),
+ E = AddressPoints.end(); I != E; ++I) {
+ const BaseSubobject& Base = I->first;
+ uint64_t Index = I->second;
+
+ AddressPointsByIndex.insert(std::make_pair(Index, Base));
+ }
+
+ for (unsigned I = 0, E = Components.size(); I != E; ++I) {
+ uint64_t Index = I;
+
+ Out << llvm::format("%4d | ", I);
+
+ const VTableComponent &Component = Components[I];
+
+ // Dump the component.
+ switch (Component.getKind()) {
+
+ case VTableComponent::CK_VCallOffset:
+ Out << "vcall_offset ("
+ << Component.getVCallOffset().getQuantity()
+ << ")";
+ break;
+
+ case VTableComponent::CK_VBaseOffset:
+ Out << "vbase_offset ("
+ << Component.getVBaseOffset().getQuantity()
+ << ")";
+ break;
+
+ case VTableComponent::CK_OffsetToTop:
+ Out << "offset_to_top ("
+ << Component.getOffsetToTop().getQuantity()
+ << ")";
+ break;
+
+ case VTableComponent::CK_RTTI:
+ Out << Component.getRTTIDecl()->getQualifiedNameAsString() << " RTTI";
+ break;
+
+ case VTableComponent::CK_FunctionPointer: {
+ const CXXMethodDecl *MD = Component.getFunctionDecl();
+
+ std::string Str =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+ Out << Str;
+ if (MD->isPure())
+ Out << " [pure]";
+
+ ThunkInfo Thunk = VTableThunks.lookup(I);
+ if (!Thunk.isEmpty()) {
+ // If this function pointer has a return adjustment, dump it.
+ if (!Thunk.Return.isEmpty()) {
+ Out << "\n [return adjustment: ";
+ Out << Thunk.Return.NonVirtual << " non-virtual";
+
+ if (Thunk.Return.VBaseOffsetOffset) {
+ Out << ", " << Thunk.Return.VBaseOffsetOffset;
+ Out << " vbase offset offset";
+ }
+
+ Out << ']';
+ }
+
+ // If this function pointer has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "\n [this adjustment: ";
+ Out << Thunk.This.NonVirtual << " non-virtual";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " vcall offset offset";
+ }
+
+ Out << ']';
+ }
+ }
+
+ break;
+ }
+
+ case VTableComponent::CK_CompleteDtorPointer:
+ case VTableComponent::CK_DeletingDtorPointer: {
+ bool IsComplete =
+ Component.getKind() == VTableComponent::CK_CompleteDtorPointer;
+
+ const CXXDestructorDecl *DD = Component.getDestructorDecl();
+
+ Out << DD->getQualifiedNameAsString();
+ if (IsComplete)
+ Out << "() [complete]";
+ else
+ Out << "() [deleting]";
+
+ if (DD->isPure())
+ Out << " [pure]";
+
+ ThunkInfo Thunk = VTableThunks.lookup(I);
+ if (!Thunk.isEmpty()) {
+ // If this destructor has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "\n [this adjustment: ";
+ Out << Thunk.This.NonVirtual << " non-virtual";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " vcall offset offset";
+ }
+
+ Out << ']';
+ }
+ }
+
+ break;
+ }
+
+ case VTableComponent::CK_UnusedFunctionPointer: {
+ const CXXMethodDecl *MD = Component.getUnusedFunctionDecl();
+
+ std::string Str =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+ Out << "[unused] " << Str;
+ if (MD->isPure())
+ Out << " [pure]";
+ }
+
+ }
+
+ Out << '\n';
+
+ // Dump the next address point.
+ uint64_t NextIndex = Index + 1;
+ if (AddressPointsByIndex.count(NextIndex)) {
+ if (AddressPointsByIndex.count(NextIndex) == 1) {
+ const BaseSubobject &Base =
+ AddressPointsByIndex.find(NextIndex)->second;
+
+ Out << " -- (" << Base.getBase()->getQualifiedNameAsString();
+ Out << ", " << Base.getBaseOffset().getQuantity();
+ Out << ") vtable address --\n";
+ } else {
+ CharUnits BaseOffset =
+ AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
+
+ // We store the class names in a set to get a stable order.
+ std::set<std::string> ClassNames;
+ for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
+ AddressPointsByIndex.lower_bound(NextIndex), E =
+ AddressPointsByIndex.upper_bound(NextIndex); I != E; ++I) {
+ assert(I->second.getBaseOffset() == BaseOffset &&
+ "Invalid base offset!");
+ const CXXRecordDecl *RD = I->second.getBase();
+ ClassNames.insert(RD->getQualifiedNameAsString());
+ }
+
+ for (std::set<std::string>::const_iterator I = ClassNames.begin(),
+ E = ClassNames.end(); I != E; ++I) {
+ Out << " -- (" << *I;
+ Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n";
+ }
+ }
+ }
+ }
+
+ Out << '\n';
+
+ if (isBuildingConstructorVTable())
+ return;
+
+ if (MostDerivedClass->getNumVBases()) {
+ // We store the virtual base class names and their offsets in a map to get
+ // a stable order.
+
+ std::map<std::string, CharUnits> ClassNamesAndOffsets;
+ for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(),
+ E = VBaseOffsetOffsets.end(); I != E; ++I) {
+ std::string ClassName = I->first->getQualifiedNameAsString();
+ CharUnits OffsetOffset = I->second;
+ ClassNamesAndOffsets.insert(
+ std::make_pair(ClassName, OffsetOffset));
+ }
+
+ Out << "Virtual base offset offsets for '";
+ Out << MostDerivedClass->getQualifiedNameAsString() << "' (";
+ Out << ClassNamesAndOffsets.size();
+ Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n";
+
+ for (std::map<std::string, CharUnits>::const_iterator I =
+ ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();
+ I != E; ++I)
+ Out << " " << I->first << " | " << I->second.getQuantity() << '\n';
+
+ Out << "\n";
+ }
+
+ if (!Thunks.empty()) {
+ // We store the method names in a map to get a stable order.
+ std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
+
+ for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end();
+ I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ std::string MethodName =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+
+ MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
+ }
+
+ for (std::map<std::string, const CXXMethodDecl *>::const_iterator I =
+ MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end();
+ I != E; ++I) {
+ const std::string &MethodName = I->first;
+ const CXXMethodDecl *MD = I->second;
+
+ ThunkInfoVectorTy ThunksVector = Thunks[MD];
+ std::sort(ThunksVector.begin(), ThunksVector.end());
+
+ Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
+ Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
+
+ for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
+ const ThunkInfo &Thunk = ThunksVector[I];
+
+ Out << llvm::format("%4d | ", I);
+
+ // If this function pointer has a return pointer adjustment, dump it.
+ if (!Thunk.Return.isEmpty()) {
+ Out << "return adjustment: " << Thunk.This.NonVirtual;
+ Out << " non-virtual";
+ if (Thunk.Return.VBaseOffsetOffset) {
+ Out << ", " << Thunk.Return.VBaseOffsetOffset;
+ Out << " vbase offset offset";
+ }
+
+ if (!Thunk.This.isEmpty())
+ Out << "\n ";
+ }
+
+ // If this function pointer has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "this adjustment: ";
+ Out << Thunk.This.NonVirtual << " non-virtual";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " vcall offset offset";
+ }
+ }
+
+ Out << '\n';
+ }
+
+ Out << '\n';
+ }
+ }
+
+ // Compute the vtable indices for all the member functions.
+ // Store them in a map keyed by the index so we'll get a sorted table.
+ std::map<uint64_t, std::string> IndicesMap;
+
+ for (CXXRecordDecl::method_iterator i = MostDerivedClass->method_begin(),
+ e = MostDerivedClass->method_end(); i != e; ++i) {
+ const CXXMethodDecl *MD = *i;
+
+ // We only want virtual member functions.
+ if (!MD->isVirtual())
+ continue;
+
+ std::string MethodName =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))] =
+ MethodName + " [complete]";
+ IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] =
+ MethodName + " [deleting]";
+ } else {
+ IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName;
+ }
+ }
+
+ // Print the vtable indices for all the member functions.
+ if (!IndicesMap.empty()) {
+ Out << "VTable indices for '";
+ Out << MostDerivedClass->getQualifiedNameAsString();
+ Out << "' (" << IndicesMap.size() << " entries).\n";
+
+ for (std::map<uint64_t, std::string>::const_iterator I = IndicesMap.begin(),
+ E = IndicesMap.end(); I != E; ++I) {
+ uint64_t VTableIndex = I->first;
+ const std::string &MethodName = I->second;
+
+ Out << llvm::format(" %4u | ", VTableIndex) << MethodName << '\n';
+ }
+ }
+
+ Out << '\n';
+}
+
+}
+
+VTableLayout::VTableLayout(uint64_t NumVTableComponents,
+ const VTableComponent *VTableComponents,
+ uint64_t NumVTableThunks,
+ const VTableThunkTy *VTableThunks,
+ const AddressPointsMapTy &AddressPoints)
+ : NumVTableComponents(NumVTableComponents),
+ VTableComponents(new VTableComponent[NumVTableComponents]),
+ NumVTableThunks(NumVTableThunks),
+ VTableThunks(new VTableThunkTy[NumVTableThunks]),
+ AddressPoints(AddressPoints) {
+ std::copy(VTableComponents, VTableComponents+NumVTableComponents,
+ this->VTableComponents);
+ std::copy(VTableThunks, VTableThunks+NumVTableThunks, this->VTableThunks);
+}
+
+VTableLayout::~VTableLayout() {
+ delete[] VTableComponents;
+}
+
+VTableContext::~VTableContext() {
+ llvm::DeleteContainerSeconds(VTableLayouts);
+}
+
+static void
+CollectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
+ VTableBuilder::PrimaryBasesSetVectorTy &PrimaryBases) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ if (!PrimaryBase)
+ return;
+
+ CollectPrimaryBases(PrimaryBase, Context, PrimaryBases);
+
+ if (!PrimaryBases.insert(PrimaryBase))
+ llvm_unreachable("Found a duplicate primary base!");
+}
+
+void VTableContext::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
+
+ // Itanium C++ ABI 2.5.2:
+ // The order of the virtual function pointers in a virtual table is the
+ // order of declaration of the corresponding member functions in the class.
+ //
+ // There is an entry for any virtual function declared in a class,
+ // whether it is a new function or overrides a base class function,
+ // unless it overrides a function from the primary base, and conversion
+ // between their return types does not require an adjustment.
+
+ int64_t CurrentIndex = 0;
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ if (PrimaryBase) {
+ assert(PrimaryBase->isCompleteDefinition() &&
+ "Should have the definition decl of the primary base!");
+
+ // Since the record decl shares its vtable pointer with the primary base
+ // we need to start counting at the end of the primary base's vtable.
+ CurrentIndex = getNumVirtualFunctionPointers(PrimaryBase);
+ }
+
+ // Collect all the primary bases, so we can check whether methods override
+ // a method from the base.
+ VTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
+ CollectPrimaryBases(RD, Context, PrimaryBases);
+
+ const CXXDestructorDecl *ImplicitVirtualDtor = 0;
+
+ for (CXXRecordDecl::method_iterator i = RD->method_begin(),
+ e = RD->method_end(); i != e; ++i) {
+ const CXXMethodDecl *MD = *i;
+
+ // We only want virtual methods.
+ if (!MD->isVirtual())
+ continue;
+
+ // Check if this method overrides a method in the primary base.
+ if (const CXXMethodDecl *OverriddenMD =
+ FindNearestOverriddenMethod(MD, PrimaryBases)) {
+ // Check if converting from the return type of the method to the
+ // return type of the overridden method requires conversion.
+ if (ComputeReturnAdjustmentBaseOffset(Context, MD,
+ OverriddenMD).isEmpty()) {
+ // This index is shared between the index in the vtable of the primary
+ // base class.
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ const CXXDestructorDecl *OverriddenDD =
+ cast<CXXDestructorDecl>(OverriddenMD);
+
+ // Add both the complete and deleting entries.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
+ getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
+ getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
+ } else {
+ MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD);
+ }
+
+ // We don't need to add an entry for this method.
+ continue;
+ }
+ }
+
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ if (MD->isImplicit()) {
+ assert(!ImplicitVirtualDtor &&
+ "Did already see an implicit virtual dtor!");
+ ImplicitVirtualDtor = DD;
+ continue;
+ }
+
+ // Add the complete dtor.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
+
+ // Add the deleting dtor.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
+ } else {
+ // Add the entry.
+ MethodVTableIndices[MD] = CurrentIndex++;
+ }
+ }
+
+ if (ImplicitVirtualDtor) {
+ // Itanium C++ ABI 2.5.2:
+ // If a class has an implicitly-defined virtual destructor,
+ // its entries come after the declared virtual function pointers.
+
+ // Add the complete dtor.
+ MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] =
+ CurrentIndex++;
+
+ // Add the deleting dtor.
+ MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Deleting)] =
+ CurrentIndex++;
+ }
+
+ NumVirtualFunctionPointers[RD] = CurrentIndex;
+}
+
+uint64_t VTableContext::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
+ NumVirtualFunctionPointers.find(RD);
+ if (I != NumVirtualFunctionPointers.end())
+ return I->second;
+
+ ComputeMethodVTableIndices(RD);
+
+ I = NumVirtualFunctionPointers.find(RD);
+ assert(I != NumVirtualFunctionPointers.end() && "Did not find entry!");
+ return I->second;
+}
+
+uint64_t VTableContext::getMethodVTableIndex(GlobalDecl GD) {
+ MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
+ if (I != MethodVTableIndices.end())
+ return I->second;
+
+ const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
+
+ ComputeMethodVTableIndices(RD);
+
+ I = MethodVTableIndices.find(GD);
+ assert(I != MethodVTableIndices.end() && "Did not find index!");
+ return I->second;
+}
+
+CharUnits
+VTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *VBase) {
+ ClassPairTy ClassPair(RD, VBase);
+
+ VirtualBaseClassOffsetOffsetsMapTy::iterator I =
+ VirtualBaseClassOffsetOffsets.find(ClassPair);
+ if (I != VirtualBaseClassOffsetOffsets.end())
+ return I->second;
+
+ VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/0,
+ BaseSubobject(RD, CharUnits::Zero()),
+ /*BaseIsVirtual=*/false,
+ /*OffsetInLayoutClass=*/CharUnits::Zero());
+
+ for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
+ Builder.getVBaseOffsetOffsets().begin(),
+ E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
+ // Insert all types.
+ ClassPairTy ClassPair(RD, I->first);
+
+ VirtualBaseClassOffsetOffsets.insert(
+ std::make_pair(ClassPair, I->second));
+ }
+
+ I = VirtualBaseClassOffsetOffsets.find(ClassPair);
+ assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
+
+ return I->second;
+}
+
+static VTableLayout *CreateVTableLayout(const VTableBuilder &Builder) {
+ SmallVector<VTableLayout::VTableThunkTy, 1>
+ VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
+ std::sort(VTableThunks.begin(), VTableThunks.end());
+
+ return new VTableLayout(Builder.getNumVTableComponents(),
+ Builder.vtable_component_begin(),
+ VTableThunks.size(),
+ VTableThunks.data(),
+ Builder.getAddressPoints());
+}
+
+void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
+ const VTableLayout *&Entry = VTableLayouts[RD];
+
+ // Check if we've computed this information before.
+ if (Entry)
+ return;
+
+ VTableBuilder Builder(*this, RD, CharUnits::Zero(),
+ /*MostDerivedClassIsVirtual=*/0, RD);
+ Entry = CreateVTableLayout(Builder);
+
+ // Add the known thunks.
+ Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
+
+ // If we don't have the vbase information for this class, insert it.
+ // getVirtualBaseOffsetOffset will compute it separately without computing
+ // the rest of the vtable related information.
+ if (!RD->getNumVBases())
+ return;
+
+ const RecordType *VBaseRT =
+ RD->vbases_begin()->getType()->getAs<RecordType>();
+ const CXXRecordDecl *VBase = cast<CXXRecordDecl>(VBaseRT->getDecl());
+
+ if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
+ return;
+
+ for (VTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
+ Builder.getVBaseOffsetOffsets().begin(),
+ E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
+ // Insert all types.
+ ClassPairTy ClassPair(RD, I->first);
+
+ VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
+ }
+}
+
+VTableLayout *VTableContext::createConstructionVTableLayout(
+ const CXXRecordDecl *MostDerivedClass,
+ CharUnits MostDerivedClassOffset,
+ bool MostDerivedClassIsVirtual,
+ const CXXRecordDecl *LayoutClass) {
+ VTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset,
+ MostDerivedClassIsVirtual, LayoutClass);
+ return CreateVTableLayout(Builder);
+}