summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
-rw-r--r--contrib/llvm/tools/clang/lib/AST/APValue.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp419
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp431
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp1144
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp124
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXABI.h4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Comment.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp159
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp94
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp66
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp205
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp579
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp54
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp187
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Mangle.cpp92
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp174
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NSAPI.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp454
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp91
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Type.cpp143
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp334
37 files changed, 3574 insertions, 1791 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp
index 0fa0216..91f1e20 100644
--- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp
@@ -573,7 +573,7 @@ bool APValue::hasLValuePath() const {
ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
assert(isLValue() && hasLValuePath() && "Invalid accessor");
const LV &LVal = *((const LV*)(const char*)Data.buffer);
- return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
+ return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength);
}
unsigned APValue::getLValueCallIndex() const {
@@ -623,7 +623,7 @@ ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
assert(isMemberPointer() && "Invalid accessor");
const MemberPointerData &MPD =
*((const MemberPointerData *)(const char *)Data.buffer);
- return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength);
+ return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength);
}
void APValue::MakeLValue() {
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
index bccdae9..6b864d0 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -699,9 +699,10 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
1, // opencl_global
2, // opencl_local
3, // opencl_constant
- 4, // cuda_device
- 5, // cuda_constant
- 6 // cuda_shared
+ 4, // opencl_generic
+ 5, // cuda_device
+ 6, // cuda_constant
+ 7 // cuda_shared
};
return &FakeAddrSpaceMap;
} else {
@@ -722,35 +723,28 @@ static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI,
llvm_unreachable("getAddressSpaceMapMangling() doesn't cover anything.");
}
-ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
+ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins)
- : FunctionProtoTypes(this_()),
- TemplateSpecializationTypes(this_()),
- DependentTemplateSpecializationTypes(this_()),
- SubstTemplateTemplateParmPacks(this_()),
- GlobalNestedNameSpecifier(nullptr),
- Int128Decl(nullptr), UInt128Decl(nullptr), Float128StubDecl(nullptr),
- BuiltinVaListDecl(nullptr),
- ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr),
- ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
- CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr),
- FILEDecl(nullptr),
- jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr),
- BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr),
- cudaConfigureCallDecl(nullptr),
- NullTypeSourceInfo(QualType()),
- FirstLocalImport(), LastLocalImport(),
- SourceMgr(SM), LangOpts(LOpts),
- AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts),
- Idents(idents), Selectors(sels),
- BuiltinInfo(builtins),
- DeclarationNames(*this),
- ExternalSource(nullptr), Listener(nullptr),
- Comments(SM), CommentsLoaded(false),
- CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
- LastSDM(nullptr, 0)
-{
+ : FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()),
+ DependentTemplateSpecializationTypes(this_()),
+ SubstTemplateTemplateParmPacks(this_()),
+ GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr),
+ UInt128Decl(nullptr), Float128StubDecl(nullptr),
+ BuiltinVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr),
+ ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
+ CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr),
+ FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr),
+ ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
+ BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
+ FirstLocalImport(), LastLocalImport(),
+ SourceMgr(SM), LangOpts(LOpts),
+ SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFile, SM)),
+ AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts),
+ Idents(idents), Selectors(sels), BuiltinInfo(builtins),
+ DeclarationNames(*this), ExternalSource(nullptr), Listener(nullptr),
+ Comments(SM), CommentsLoaded(false),
+ CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) {
TUDecl = TranslationUnitDecl::Create(*this);
}
@@ -1413,9 +1407,9 @@ std::pair<CharUnits, CharUnits>
ASTContext::getTypeInfoInChars(const Type *T) const {
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
return getConstantArrayInfoInChars(*this, CAT);
- std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
- return std::make_pair(toCharUnitsFromBits(Info.first),
- toCharUnitsFromBits(Info.second));
+ TypeInfo Info = getTypeInfo(T);
+ return std::make_pair(toCharUnitsFromBits(Info.Width),
+ toCharUnitsFromBits(Info.Align));
}
std::pair<CharUnits, CharUnits>
@@ -1423,14 +1417,23 @@ ASTContext::getTypeInfoInChars(QualType T) const {
return getTypeInfoInChars(T.getTypePtr());
}
-std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const {
- TypeInfoMap::iterator it = MemoizedTypeInfo.find(T);
- if (it != MemoizedTypeInfo.end())
- return it->second;
+bool ASTContext::isAlignmentRequired(const Type *T) const {
+ return getTypeInfo(T).AlignIsRequired;
+}
+
+bool ASTContext::isAlignmentRequired(QualType T) const {
+ return isAlignmentRequired(T.getTypePtr());
+}
+
+TypeInfo ASTContext::getTypeInfo(const Type *T) const {
+ TypeInfoMap::iterator I = MemoizedTypeInfo.find(T);
+ if (I != MemoizedTypeInfo.end())
+ return I->second;
- std::pair<uint64_t, unsigned> Info = getTypeInfoImpl(T);
- MemoizedTypeInfo.insert(std::make_pair(T, Info));
- return Info;
+ // This call can invalidate MemoizedTypeInfo[T], so we need a second lookup.
+ TypeInfo TI = getTypeInfoImpl(T);
+ MemoizedTypeInfo[T] = TI;
+ return TI;
}
/// getTypeInfoImpl - Return the size of the specified type, in bits. This
@@ -1439,10 +1442,10 @@ std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const {
/// FIXME: Pointers into different addr spaces could have different sizes and
/// alignment requirements: getPointerInfo should take an AddrSpace, this
/// should take a QualType, &c.
-std::pair<uint64_t, unsigned>
-ASTContext::getTypeInfoImpl(const Type *T) const {
- uint64_t Width=0;
- unsigned Align=8;
+TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
+ uint64_t Width = 0;
+ unsigned Align = 8;
+ bool AlignIsRequired = false;
switch (T->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
@@ -1471,12 +1474,12 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::ConstantArray: {
const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
- std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType());
+ TypeInfo EltInfo = getTypeInfo(CAT->getElementType());
uint64_t Size = CAT->getSize().getZExtValue();
- assert((Size == 0 || EltInfo.first <= (uint64_t)(-1)/Size) &&
+ assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) &&
"Overflow in array type bit size evaluation");
- Width = EltInfo.first*Size;
- Align = EltInfo.second;
+ Width = EltInfo.Width * Size;
+ Align = EltInfo.Align;
if (!getTargetInfo().getCXXABI().isMicrosoft() ||
getTargetInfo().getPointerWidth(0) == 64)
Width = llvm::RoundUpToAlignment(Width, Align);
@@ -1485,8 +1488,8 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::ExtVector:
case Type::Vector: {
const VectorType *VT = cast<VectorType>(T);
- std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType());
- Width = EltInfo.first*VT->getNumElements();
+ TypeInfo EltInfo = getTypeInfo(VT->getElementType());
+ Width = EltInfo.Width * VT->getNumElements();
Align = Width;
// If the alignment is not a power of 2, round up to the next power of 2.
// This happens for non-power-of-2 length vectors.
@@ -1638,10 +1641,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::Complex: {
// Complex types have the same alignment as their elements, but twice the
// size.
- std::pair<uint64_t, unsigned> EltInfo =
- getTypeInfo(cast<ComplexType>(T)->getElementType());
- Width = EltInfo.first*2;
- Align = EltInfo.second;
+ TypeInfo EltInfo = getTypeInfo(cast<ComplexType>(T)->getElementType());
+ Width = EltInfo.Width * 2;
+ Align = EltInfo.Align;
break;
}
case Type::ObjCObject:
@@ -1692,16 +1694,18 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::Typedef: {
const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl();
- std::pair<uint64_t, unsigned> Info
- = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
+ TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
// If the typedef has an aligned attribute on it, it overrides any computed
// alignment we have. This violates the GCC documentation (which says that
// attribute(aligned) can only round up) but matches its implementation.
- if (unsigned AttrAlign = Typedef->getMaxAlignment())
+ if (unsigned AttrAlign = Typedef->getMaxAlignment()) {
Align = AttrAlign;
- else
- Align = Info.second;
- Width = Info.first;
+ AlignIsRequired = true;
+ } else {
+ Align = Info.Align;
+ AlignIsRequired = Info.AlignIsRequired;
+ }
+ Width = Info.Width;
break;
}
@@ -1714,10 +1718,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::Atomic: {
// Start with the base type information.
- std::pair<uint64_t, unsigned> Info
- = getTypeInfo(cast<AtomicType>(T)->getValueType());
- Width = Info.first;
- Align = Info.second;
+ TypeInfo Info = getTypeInfo(cast<AtomicType>(T)->getValueType());
+ Width = Info.Width;
+ Align = Info.Align;
// If the size of the type doesn't exceed the platform's max
// atomic promotion width, make the size and alignment more
@@ -1735,7 +1738,7 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
}
assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
- return std::make_pair(Width, Align);
+ return TypeInfo(Width, Align, AlignIsRequired);
}
/// toCharUnitsFromBits - Convert a size in bits to a size in characters.
@@ -1771,13 +1774,12 @@ CharUnits ASTContext::getTypeAlignInChars(const Type *T) const {
/// alignment in cases where it is beneficial for performance to overalign
/// a data type.
unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
- unsigned ABIAlign = getTypeAlign(T);
+ TypeInfo TI = getTypeInfo(T);
+ unsigned ABIAlign = TI.Align;
if (Target->getTriple().getArch() == llvm::Triple::xcore)
return ABIAlign; // Never overalign on XCore.
- const TypedefType *TT = T->getAs<TypedefType>();
-
// Double and long long should be naturally aligned if possible.
T = T->getBaseElementTypeUnsafe();
if (const ComplexType *CT = T->getAs<ComplexType>())
@@ -1787,7 +1789,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
T->isSpecificBuiltinType(BuiltinType::ULongLong))
// Don't increase the alignment if an alignment attribute was specified on a
// typedef declaration.
- if (!TT || !TT->getDecl()->getMaxAlignment())
+ if (!TI.AlignIsRequired)
return std::max(ABIAlign, (unsigned)getTypeSize(T));
return ABIAlign;
@@ -2110,6 +2112,62 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD,
L->DeducedReturnType(FD, ResultType);
}
+/// Get a function type and produce the equivalent function type with the
+/// specified exception specification. Type sugar that can be present on a
+/// declaration of a function with an exception specification is permitted
+/// and preserved. Other type sugar (for instance, typedefs) is not.
+static QualType getFunctionTypeWithExceptionSpec(
+ ASTContext &Context, QualType Orig,
+ const FunctionProtoType::ExceptionSpecInfo &ESI) {
+ // Might have some parens.
+ if (auto *PT = dyn_cast<ParenType>(Orig))
+ return Context.getParenType(
+ getFunctionTypeWithExceptionSpec(Context, PT->getInnerType(), ESI));
+
+ // Might have a calling-convention attribute.
+ if (auto *AT = dyn_cast<AttributedType>(Orig))
+ return Context.getAttributedType(
+ AT->getAttrKind(),
+ getFunctionTypeWithExceptionSpec(Context, AT->getModifiedType(), ESI),
+ getFunctionTypeWithExceptionSpec(Context, AT->getEquivalentType(),
+ ESI));
+
+ // Anything else must be a function type. Rebuild it with the new exception
+ // specification.
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(Orig);
+ return Context.getFunctionType(
+ Proto->getReturnType(), Proto->getParamTypes(),
+ Proto->getExtProtoInfo().withExceptionSpec(ESI));
+}
+
+void ASTContext::adjustExceptionSpec(
+ FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI,
+ bool AsWritten) {
+ // Update the type.
+ QualType Updated =
+ getFunctionTypeWithExceptionSpec(*this, FD->getType(), ESI);
+ FD->setType(Updated);
+
+ if (!AsWritten)
+ return;
+
+ // Update the type in the type source information too.
+ if (TypeSourceInfo *TSInfo = FD->getTypeSourceInfo()) {
+ // If the type and the type-as-written differ, we may need to update
+ // the type-as-written too.
+ if (TSInfo->getType() != FD->getType())
+ Updated = getFunctionTypeWithExceptionSpec(*this, TSInfo->getType(), ESI);
+
+ // FIXME: When we get proper type location information for exceptions,
+ // we'll also have to rebuild the TypeSourceInfo. For now, we just patch
+ // up the TypeSourceInfo;
+ assert(TypeLoc::getFullDataSizeForType(Updated) ==
+ TypeLoc::getFullDataSizeForType(TSInfo->getType()) &&
+ "TypeLoc size mismatch from updating exception specification");
+ TSInfo->overrideType(Updated);
+ }
+}
+
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType ASTContext::getComplexType(QualType T) const {
@@ -2840,7 +2898,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
// Determine whether the type being created is already canonical or not.
bool isCanonical =
- EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) &&
+ EPI.ExceptionSpec.Type == EST_None && isCanonicalResultType(ResultTy) &&
!EPI.HasTrailingReturn;
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
if (!ArgArray[i].isCanonicalAsParam())
@@ -2857,8 +2915,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI;
CanonicalEPI.HasTrailingReturn = false;
- CanonicalEPI.ExceptionSpecType = EST_None;
- CanonicalEPI.NumExceptions = 0;
+ CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo();
// Result types do not have ARC lifetime qualifiers.
QualType CanResultTy = getCanonicalType(ResultTy);
@@ -2886,13 +2943,13 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
// specification.
size_t Size = sizeof(FunctionProtoType) +
NumArgs * sizeof(QualType);
- if (EPI.ExceptionSpecType == EST_Dynamic) {
- Size += EPI.NumExceptions * sizeof(QualType);
- } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
+ if (EPI.ExceptionSpec.Type == EST_Dynamic) {
+ Size += EPI.ExceptionSpec.Exceptions.size() * sizeof(QualType);
+ } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) {
Size += sizeof(Expr*);
- } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
+ } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) {
Size += 2 * sizeof(FunctionDecl*);
- } else if (EPI.ExceptionSpecType == EST_Unevaluated) {
+ } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) {
Size += sizeof(FunctionDecl*);
}
if (EPI.ConsumedParameters)
@@ -4099,7 +4156,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
case TemplateArgument::Declaration: {
ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
- return TemplateArgument(D, Arg.isDeclForReferenceParam());
+ return TemplateArgument(D, Arg.getParamTypeForDecl());
}
case TemplateArgument::NullPtr:
@@ -4188,7 +4245,8 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
}
case NestedNameSpecifier::Global:
- // The global specifier is canonical and unique.
+ case NestedNameSpecifier::Super:
+ // The global specifier and __super specifer are canonical and unique.
return NNS;
}
@@ -4414,7 +4472,11 @@ unsigned ASTContext::getIntegerRank(const Type *T) const {
QualType ASTContext::isPromotableBitField(Expr *E) const {
if (E->isTypeDependent() || E->isValueDependent())
return QualType();
-
+
+ // FIXME: We should not do this unless E->refersToBitField() is true. This
+ // matters in C where getSourceBitField() will find bit-fields for various
+ // cases where the source expression is not a bit-field designator.
+
FieldDecl *Field = E->getSourceBitField(); // FIXME: conditional bit-fields?
if (!Field)
return QualType();
@@ -4423,9 +4485,20 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
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.
- // For instance, unsigned long bf : 4 gets promoted to signed int.
+ // C++ [conv.prom]p5:
+ // A prvalue for an integral bit-field can be converted to a prvalue of type
+ // int if int can represent all the values of the bit-field; otherwise, it
+ // can be converted to unsigned int if unsigned int can represent all the
+ // values of the bit-field. If the bit-field is larger yet, no integral
+ // promotion applies to it.
+ // C11 6.3.1.1/2:
+ // [For a bit-field of type _Bool, int, signed int, or unsigned int:]
+ // If an int can represent all values of the original type (as restricted by
+ // the width, for a bit-field), the value is converted to an int; otherwise,
+ // it is converted to an unsigned int.
+ //
+ // FIXME: C does not permit promotion of a 'long : 3' bitfield to int.
+ // We perform that promotion here to match GCC and C++.
if (BitWidth < IntSize)
return IntTy;
@@ -4433,9 +4506,10 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
return FT->isSignedIntegerType() ? IntTy : UnsignedIntTy;
// Types bigger than int are not subject to promotions, and therefore act
- // like the base type.
- // FIXME: This doesn't quite match what gcc does, but what gcc does here
- // is ridiculous.
+ // like the base type. GCC has some weird bugs in this area that we
+ // deliberately do not follow (GCC follows a pre-standard resolution to
+ // C's DR315 which treats bit-width as being part of the type, and this leaks
+ // into their semantics in some cases).
return QualType();
}
@@ -5090,13 +5164,15 @@ void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const {
}
void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
- const FieldDecl *Field) const {
+ const FieldDecl *Field,
+ QualType *NotEncodedT) const {
// We follow the behavior of gcc, expanding structures which are
// directly pointed to, and expanding embedded structures. Note that
// these rules are sufficient to prevent recursive encoding of the
// same type.
getObjCEncodingForTypeImpl(T, S, true, true, Field,
- true /* outermost type */);
+ true /* outermost type */, false, false,
+ false, false, false, NotEncodedT);
}
void ASTContext::getObjCEncodingForPropertyType(QualType T,
@@ -5222,7 +5298,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
bool StructField,
bool EncodeBlockParameters,
bool EncodeClassNames,
- bool EncodePointerToObjCTypedef) const {
+ bool EncodePointerToObjCTypedef,
+ QualType *NotEncodedT) const {
CanQualType CT = getCanonicalType(T);
switch (CT->getTypeClass()) {
case Type::Builtin:
@@ -5238,16 +5315,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::Complex: {
const ComplexType *CT = T->castAs<ComplexType>();
S += 'j';
- getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr,
- false, false);
+ getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr);
return;
}
case Type::Atomic: {
const AtomicType *AT = T->castAs<AtomicType>();
S += 'A';
- getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr,
- false, false);
+ getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr);
return;
}
@@ -5318,7 +5393,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
getLegacyIntegralTypeEncoding(PointeeTy);
getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures,
- nullptr);
+ nullptr, false, false, false, false, false, false,
+ NotEncodedT);
return;
}
@@ -5346,7 +5422,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
getObjCEncodingForTypeImpl(AT->getElementType(), S,
- false, ExpandStructures, FD);
+ false, ExpandStructures, FD,
+ false, false, false, false, false, false,
+ NotEncodedT);
S += ']';
}
return;
@@ -5378,7 +5456,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (ExpandStructures) {
S += '=';
if (!RDecl->isUnion()) {
- getObjCEncodingForStructureImpl(RDecl, S, FD);
+ getObjCEncodingForStructureImpl(RDecl, S, FD, true, NotEncodedT);
} else {
for (const auto *Field : RDecl->fields()) {
if (FD) {
@@ -5397,7 +5475,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
getObjCEncodingForTypeImpl(qt, S, false, true,
FD, /*OutermostType*/false,
/*EncodingProperty*/false,
- /*StructField*/true);
+ /*StructField*/true,
+ false, false, false, NotEncodedT);
}
}
}
@@ -5417,7 +5496,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
getObjCEncodingForTypeImpl(
FT->getReturnType(), S, ExpandPointedToStructures, ExpandStructures,
FD, false /* OutermostType */, EncodingProperty,
- false /* StructField */, EncodeBlockParameters, EncodeClassNames);
+ false /* StructField */, EncodeBlockParameters, EncodeClassNames, false,
+ NotEncodedT);
// Block self
S += "@?";
// Block parameters
@@ -5426,7 +5506,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
getObjCEncodingForTypeImpl(
I, S, ExpandPointedToStructures, ExpandStructures, FD,
false /* OutermostType */, EncodingProperty,
- false /* StructField */, EncodeBlockParameters, EncodeClassNames);
+ false /* StructField */, EncodeBlockParameters, EncodeClassNames,
+ false, NotEncodedT);
}
S += '>';
}
@@ -5468,7 +5549,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
else
getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD,
false, false, false, false, false,
- EncodePointerToObjCTypedef);
+ EncodePointerToObjCTypedef,
+ NotEncodedT);
}
S += '}';
return;
@@ -5555,19 +5637,21 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
// gcc just blithely ignores member pointers.
// FIXME: we shoul do better than that. 'M' is available.
case Type::MemberPointer:
- return;
-
+ // This matches gcc's encoding, even though technically it is insufficient.
+ //FIXME. We should do a better job than gcc.
case Type::Vector:
case Type::ExtVector:
- // This matches gcc's encoding, even though technically it is
- // insufficient.
- // FIXME. We should do a better job than gcc.
- return;
-
+ // Until we have a coherent encoding of these three types, issue warning.
+ { if (NotEncodedT)
+ *NotEncodedT = T;
+ return;
+ }
+
+ // We could see an undeduced auto type here during error recovery.
+ // Just ignore it.
case Type::Auto:
- // We could see an undeduced auto type here during error recovery.
- // Just ignore it.
return;
+
#define ABSTRACT_TYPE(KIND, BASE)
#define TYPE(KIND, BASE)
@@ -5586,7 +5670,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
std::string &S,
const FieldDecl *FD,
- bool includeVBases) const {
+ bool includeVBases,
+ QualType *NotEncodedT) const {
assert(RDecl && "Expected non-null RecordDecl");
assert(!RDecl->isUnion() && "Should not be called for unions");
if (!RDecl->getDefinition())
@@ -5610,12 +5695,11 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
}
unsigned i = 0;
- for (RecordDecl::field_iterator Field = RDecl->field_begin(),
- FieldEnd = RDecl->field_end();
- Field != FieldEnd; ++Field, ++i) {
+ for (auto *Field : RDecl->fields()) {
uint64_t offs = layout.getFieldOffset(i);
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
- std::make_pair(offs, *Field));
+ std::make_pair(offs, Field));
+ ++i;
}
if (CXXRec && includeVBases) {
@@ -5691,7 +5775,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
// in the initial structure. Note that this differs from gcc which
// expands virtual bases each time one is encountered in the hierarchy,
// making the encoding type bigger than it really is.
- getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false);
+ getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false,
+ NotEncodedT);
assert(!base->isEmpty());
#ifndef NDEBUG
CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize());
@@ -5715,7 +5800,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
getObjCEncodingForTypeImpl(qt, S, false, true, FD,
/*OutermostType*/false,
/*EncodingProperty*/false,
- /*StructField*/true);
+ /*StructField*/true,
+ false, false, false, NotEncodedT);
#ifndef NDEBUG
CurOffs += getTypeSize(field->getType());
#endif
@@ -6654,11 +6740,9 @@ void getIntersectionOfProtocols(ASTContext &Context,
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
Context.CollectInheritedProtocols(RHS->getInterface(),
RHSInheritedProtocols);
- for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
- RHSInheritedProtocols.begin(),
- E = RHSInheritedProtocols.end(); I != E; ++I)
- if (InheritedProtocolSet.count((*I)))
- IntersectionOfProtocols.push_back((*I));
+ for (ObjCProtocolDecl *ProtDecl : RHSInheritedProtocols)
+ if (InheritedProtocolSet.count(ProtDecl))
+ IntersectionOfProtocols.push_back(ProtDecl);
}
}
@@ -6708,58 +6792,40 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
if (LHS->getNumProtocols() == 0)
return true;
- // Okay, we know the LHS has protocol qualifiers. If the RHS doesn't,
- // more detailed analysis is required.
- if (RHS->getNumProtocols() == 0) {
- // OK, if LHS is a superclass of RHS *and*
- // this superclass is assignment compatible with LHS.
- // false otherwise.
- bool IsSuperClass =
- LHS->getInterface()->isSuperClassOf(RHS->getInterface());
- if (IsSuperClass) {
- // OK if conversion of LHS to SuperClass results in narrowing of types
- // ; i.e., SuperClass may implement at least one of the protocols
- // in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok.
- // But not SuperObj<P1,P2,P3> = lhs<P1,P2>.
- llvm::SmallPtrSet<ObjCProtocolDecl *, 8> SuperClassInheritedProtocols;
- CollectInheritedProtocols(RHS->getInterface(), SuperClassInheritedProtocols);
- // If super class has no protocols, it is not a match.
- if (SuperClassInheritedProtocols.empty())
- return false;
+ // Okay, we know the LHS has protocol qualifiers. But RHS may or may not.
+ // More detailed analysis is required.
+ // OK, if LHS is same or a superclass of RHS *and*
+ // this LHS, or as RHS's super class is assignment compatible with LHS.
+ bool IsSuperClass =
+ LHS->getInterface()->isSuperClassOf(RHS->getInterface());
+ if (IsSuperClass) {
+ // OK if conversion of LHS to SuperClass results in narrowing of types
+ // ; i.e., SuperClass may implement at least one of the protocols
+ // in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok.
+ // But not SuperObj<P1,P2,P3> = lhs<P1,P2>.
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 8> SuperClassInheritedProtocols;
+ CollectInheritedProtocols(RHS->getInterface(), SuperClassInheritedProtocols);
+ // Also, if RHS has explicit quelifiers, include them for comparing with LHS's
+ // qualifiers.
+ for (auto *RHSPI : RHS->quals())
+ SuperClassInheritedProtocols.insert(RHSPI->getCanonicalDecl());
+ // If there is no protocols associated with RHS, it is not a match.
+ if (SuperClassInheritedProtocols.empty())
+ return false;
- for (const auto *LHSProto : LHS->quals()) {
- bool SuperImplementsProtocol = false;
- for (auto *SuperClassProto : SuperClassInheritedProtocols) {
- if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) {
- SuperImplementsProtocol = true;
- break;
- }
+ for (const auto *LHSProto : LHS->quals()) {
+ bool SuperImplementsProtocol = false;
+ for (auto *SuperClassProto : SuperClassInheritedProtocols)
+ if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) {
+ SuperImplementsProtocol = true;
+ break;
}
- if (!SuperImplementsProtocol)
- return false;
- }
- return true;
- }
- return false;
- }
-
- for (const auto *LHSPI : LHS->quals()) {
- bool RHSImplementsProtocol = false;
-
- // If the RHS doesn't implement the protocol on the left, the types
- // are incompatible.
- for (auto *RHSPI : RHS->quals()) {
- if (RHSPI->lookupProtocolNamed(LHSPI->getIdentifier())) {
- RHSImplementsProtocol = true;
- break;
- }
+ if (!SuperImplementsProtocol)
+ return false;
}
- // FIXME: For better diagnostics, consider passing back the protocol name.
- if (!RHSImplementsProtocol)
- return false;
+ return true;
}
- // The RHS implements all protocols listed on the LHS.
- return true;
+ return false;
}
bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
@@ -7895,7 +7961,9 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
// We never need to emit an uninstantiated function template.
if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
return false;
- } else
+ } else if (isa<OMPThreadPrivateDecl>(D))
+ return true;
+ else
return false;
// If this is a member of a class template, we do not need to emit it.
@@ -8236,7 +8304,7 @@ namespace {
} // end namespace
-ASTContext::ParentVector
+ArrayRef<ast_type_traits::DynTypedNode>
ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
assert(Node.getMemoizationData() &&
"Invariant broken: only nodes that support memoization may be "
@@ -8249,13 +8317,12 @@ ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
}
ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData());
if (I == AllParents->end()) {
- return ParentVector();
+ return None;
}
- if (I->second.is<ast_type_traits::DynTypedNode *>()) {
- return ParentVector(1, *I->second.get<ast_type_traits::DynTypedNode *>());
+ if (auto *N = I->second.dyn_cast<ast_type_traits::DynTypedNode *>()) {
+ return llvm::makeArrayRef(N, 1);
}
- const auto &Parents = *I->second.get<ParentVector *>();
- return ParentVector(Parents.begin(), Parents.end());
+ return *I->second.get<ParentVector *>();
}
bool
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
index 8c8b1df..3212359 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
@@ -342,26 +342,22 @@ void clang::FormatASTNodeDiagnosticArgument(
assert(DC && "Should never have a null declaration context");
NeedQuotes = false;
+ // FIXME: Get the strings for DeclContext from some localized place
if (DC->isTranslationUnit()) {
- // FIXME: Get these strings from some localized place
if (Context.getLangOpts().CPlusPlus)
OS << "the global namespace";
else
OS << "the global scope";
+ } else if (DC->isClosure()) {
+ OS << "block literal";
+ } else if (isLambdaCallOperator(DC)) {
+ OS << "lambda expression";
} else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
OS << ConvertTypeToDiagnosticString(Context,
Context.getTypeDeclType(Type),
PrevArgs, QualTypeVals);
} else {
- // FIXME: Get these strings from some localized place
- if (isa<BlockDecl>(DC)) {
- OS << "block literal";
- break;
- }
- if (isLambdaCallOperator(DC)) {
- OS << "lambda expression";
- break;
- }
+ assert(isa<NamedDecl>(DC) && "Expected a NamedDecl");
NamedDecl *ND = cast<NamedDecl>(DC);
if (isa<NamespaceDecl>(ND))
OS << "namespace ";
@@ -877,6 +873,194 @@ class TemplateDiff {
return Ty->getAs<TemplateSpecializationType>();
}
+ /// DiffTypes - Fills a DiffNode with information about a type difference.
+ void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
+ TemplateTypeParmDecl *FromDefaultTypeDecl,
+ TemplateTypeParmDecl *ToDefaultTypeDecl) {
+ QualType FromType = GetType(FromIter, FromDefaultTypeDecl);
+ QualType ToType = GetType(ToIter, ToDefaultTypeDecl);
+
+ Tree.SetNode(FromType, ToType);
+ Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(),
+ ToIter.isEnd() && !ToType.isNull());
+ Tree.SetKind(DiffTree::Type);
+ if (FromType.isNull() || ToType.isNull())
+ return;
+
+ if (Context.hasSameType(FromType, ToType)) {
+ Tree.SetSame(true);
+ return;
+ }
+
+ const TemplateSpecializationType *FromArgTST =
+ GetTemplateSpecializationType(Context, FromType);
+ if (!FromArgTST)
+ return;
+
+ const TemplateSpecializationType *ToArgTST =
+ GetTemplateSpecializationType(Context, ToType);
+ if (!ToArgTST)
+ return;
+
+ if (!hasSameTemplate(FromArgTST, ToArgTST))
+ return;
+
+ Qualifiers FromQual = FromType.getQualifiers(),
+ ToQual = ToType.getQualifiers();
+ FromQual -= QualType(FromArgTST, 0).getQualifiers();
+ ToQual -= QualType(ToArgTST, 0).getQualifiers();
+ Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),
+ ToArgTST->getTemplateName().getAsTemplateDecl());
+ Tree.SetNode(FromQual, ToQual);
+ Tree.SetKind(DiffTree::Template);
+ DiffTemplate(FromArgTST, ToArgTST);
+ }
+
+ /// DiffTemplateTemplates - Fills a DiffNode with information about a
+ /// template template difference.
+ void DiffTemplateTemplates(const TSTiterator &FromIter,
+ const TSTiterator &ToIter,
+ TemplateTemplateParmDecl *FromDefaultTemplateDecl,
+ TemplateTemplateParmDecl *ToDefaultTemplateDecl) {
+ TemplateDecl *FromDecl = GetTemplateDecl(FromIter, FromDefaultTemplateDecl);
+ TemplateDecl *ToDecl = GetTemplateDecl(ToIter, ToDefaultTemplateDecl);
+ Tree.SetNode(FromDecl, ToDecl);
+ Tree.SetSame(FromDecl && ToDecl &&
+ FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());
+ Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl);
+ Tree.SetKind(DiffTree::TemplateTemplate);
+ }
+
+ /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes
+ static void InitializeNonTypeDiffVariables(
+ ASTContext &Context, const TSTiterator &Iter,
+ NonTypeTemplateParmDecl *Default, bool &HasInt, bool &HasValueDecl,
+ bool &IsNullPtr, Expr *&E, llvm::APSInt &Value, ValueDecl *&VD) {
+ HasInt = !Iter.isEnd() && Iter->getKind() == TemplateArgument::Integral;
+
+ HasValueDecl =
+ !Iter.isEnd() && Iter->getKind() == TemplateArgument::Declaration;
+
+ IsNullPtr = !Iter.isEnd() && Iter->getKind() == TemplateArgument::NullPtr;
+
+ if (HasInt)
+ Value = Iter->getAsIntegral();
+ else if (HasValueDecl)
+ VD = Iter->getAsDecl();
+ else if (!IsNullPtr)
+ E = GetExpr(Iter, Default);
+
+ if (E && Default->getType()->isPointerType())
+ IsNullPtr = CheckForNullPtr(Context, E);
+ }
+
+ /// NeedsAddressOf - Helper function for DiffNonTypes. Returns true if the
+ /// ValueDecl needs a '&' when printed.
+ static bool NeedsAddressOf(ValueDecl *VD, Expr *E,
+ NonTypeTemplateParmDecl *Default) {
+ if (!VD)
+ return false;
+
+ if (E) {
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParens())) {
+ if (UO->getOpcode() == UO_AddrOf) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (!Default->getType()->isReferenceType()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /// DiffNonTypes - Handles any template parameters not handled by DiffTypes
+ /// of DiffTemplatesTemplates, such as integer and declaration parameters.
+ void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
+ NonTypeTemplateParmDecl *FromDefaultNonTypeDecl,
+ NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) {
+ Expr *FromExpr = nullptr, *ToExpr = nullptr;
+ llvm::APSInt FromInt, ToInt;
+ ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
+ bool HasFromInt = false, HasToInt = false, HasFromValueDecl = false,
+ HasToValueDecl = false, FromNullPtr = false, ToNullPtr = false;
+ InitializeNonTypeDiffVariables(Context, FromIter, FromDefaultNonTypeDecl,
+ HasFromInt, HasFromValueDecl, FromNullPtr,
+ FromExpr, FromInt, FromValueDecl);
+ InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl,
+ HasToInt, HasToValueDecl, ToNullPtr,
+ ToExpr, ToInt, ToValueDecl);
+
+ assert(((!HasFromInt && !HasToInt) ||
+ (!HasFromValueDecl && !HasToValueDecl)) &&
+ "Template argument cannot be both integer and declaration");
+
+ unsigned ParamWidth = 128; // Safe default
+ if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType())
+ ParamWidth = Context.getIntWidth(FromDefaultNonTypeDecl->getType());
+
+ if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) {
+ Tree.SetNode(FromExpr, ToExpr);
+ Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr);
+ if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType()) {
+ if (FromExpr)
+ HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt);
+ if (ToExpr)
+ HasToInt = GetInt(Context, ToIter, ToExpr, ToInt);
+ }
+ if (HasFromInt && HasToInt) {
+ Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
+ Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
+ Tree.SetKind(DiffTree::Integer);
+ } else if (HasFromInt || HasToInt) {
+ Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
+ Tree.SetSame(false);
+ Tree.SetKind(DiffTree::Integer);
+ } else {
+ Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr) ||
+ (FromNullPtr && ToNullPtr));
+ Tree.SetNullPtr(FromNullPtr, ToNullPtr);
+ Tree.SetKind(DiffTree::Expression);
+ }
+ return;
+ }
+
+ if (HasFromInt || HasToInt) {
+ if (!HasFromInt && FromExpr)
+ HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt);
+ if (!HasToInt && ToExpr)
+ HasToInt = GetInt(Context, ToIter, ToExpr, ToInt);
+ Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
+ Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
+ Tree.SetDefault(FromIter.isEnd() && HasFromInt,
+ ToIter.isEnd() && HasToInt);
+ Tree.SetKind(DiffTree::Integer);
+ return;
+ }
+
+ if (!HasFromValueDecl && FromExpr)
+ FromValueDecl = GetValueDecl(FromIter, FromExpr);
+ if (!HasToValueDecl && ToExpr)
+ ToValueDecl = GetValueDecl(ToIter, ToExpr);
+
+ bool FromAddressOf =
+ NeedsAddressOf(FromValueDecl, FromExpr, FromDefaultNonTypeDecl);
+ bool ToAddressOf =
+ NeedsAddressOf(ToValueDecl, ToExpr, ToDefaultNonTypeDecl);
+
+ Tree.SetNullPtr(FromNullPtr, ToNullPtr);
+ Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
+ Tree.SetSame(FromValueDecl && ToValueDecl &&
+ FromValueDecl->getCanonicalDecl() ==
+ ToValueDecl->getCanonicalDecl());
+ Tree.SetDefault(FromIter.isEnd() && FromValueDecl,
+ ToIter.isEnd() && ToValueDecl);
+ Tree.SetKind(DiffTree::Declaration);
+ }
+
/// DiffTemplate - recursively visits template arguments and stores the
/// argument info into a tree.
void DiffTemplate(const TemplateSpecializationType *FromTST,
@@ -894,191 +1078,33 @@ class TemplateDiff {
// Get the parameter at index TotalArgs. If index is larger
// than the total number of parameters, then there is an
// argument pack, so re-use the last parameter.
- unsigned ParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);
- NamedDecl *ParamND = ParamsFrom->getParam(ParamIndex);
-
- // Handle Types
- if (TemplateTypeParmDecl *DefaultTTPD =
- dyn_cast<TemplateTypeParmDecl>(ParamND)) {
- QualType FromType, ToType;
- FromType = GetType(FromIter, DefaultTTPD);
- // A forward declaration can have no default arg but the actual class
- // can, don't mix up iterators and get the original parameter.
- ToType = GetType(
- ToIter, cast<TemplateTypeParmDecl>(ParamsTo->getParam(ParamIndex)));
- Tree.SetNode(FromType, ToType);
- Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(),
- ToIter.isEnd() && !ToType.isNull());
- Tree.SetKind(DiffTree::Type);
- if (!FromType.isNull() && !ToType.isNull()) {
- if (Context.hasSameType(FromType, ToType)) {
- Tree.SetSame(true);
- } else {
- Qualifiers FromQual = FromType.getQualifiers(),
- ToQual = ToType.getQualifiers();
- const TemplateSpecializationType *FromArgTST =
- GetTemplateSpecializationType(Context, FromType);
- const TemplateSpecializationType *ToArgTST =
- GetTemplateSpecializationType(Context, ToType);
-
- if (FromArgTST && ToArgTST &&
- hasSameTemplate(FromArgTST, ToArgTST)) {
- FromQual -= QualType(FromArgTST, 0).getQualifiers();
- ToQual -= QualType(ToArgTST, 0).getQualifiers();
- Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),
- ToArgTST->getTemplateName().getAsTemplateDecl());
- Tree.SetNode(FromQual, ToQual);
- Tree.SetKind(DiffTree::Template);
- DiffTemplate(FromArgTST, ToArgTST);
- }
- }
- }
- }
-
- // Handle Expressions
- if (NonTypeTemplateParmDecl *DefaultNTTPD =
- dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {
- Expr *FromExpr = nullptr, *ToExpr = nullptr;
- llvm::APSInt FromInt, ToInt;
- ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
- unsigned ParamWidth = 128; // Safe default
- if (DefaultNTTPD->getType()->isIntegralOrEnumerationType())
- ParamWidth = Context.getIntWidth(DefaultNTTPD->getType());
- bool HasFromInt = !FromIter.isEnd() &&
- FromIter->getKind() == TemplateArgument::Integral;
- bool HasToInt = !ToIter.isEnd() &&
- ToIter->getKind() == TemplateArgument::Integral;
- bool HasFromValueDecl =
- !FromIter.isEnd() &&
- FromIter->getKind() == TemplateArgument::Declaration;
- bool HasToValueDecl =
- !ToIter.isEnd() &&
- ToIter->getKind() == TemplateArgument::Declaration;
- bool FromNullPtr = !FromIter.isEnd() &&
- FromIter->getKind() == TemplateArgument::NullPtr;
- bool ToNullPtr =
- !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::NullPtr;
-
- assert(((!HasFromInt && !HasToInt) ||
- (!HasFromValueDecl && !HasToValueDecl)) &&
- "Template argument cannot be both integer and declaration");
-
- if (HasFromInt)
- FromInt = FromIter->getAsIntegral();
- else if (HasFromValueDecl)
- FromValueDecl = FromIter->getAsDecl();
- else if (!FromNullPtr)
- FromExpr = GetExpr(FromIter, DefaultNTTPD);
-
- if (HasToInt)
- ToInt = ToIter->getAsIntegral();
- else if (HasToValueDecl)
- ToValueDecl = ToIter->getAsDecl();
- else if (!ToNullPtr)
- ToExpr = GetExpr(ToIter, DefaultNTTPD);
-
- bool TemplateArgumentIsPointerType =
- DefaultNTTPD->getType()->isPointerType();
- if (FromExpr && TemplateArgumentIsPointerType) {
- FromNullPtr = CheckForNullPtr(FromExpr);
- }
- if (ToExpr && TemplateArgumentIsPointerType) {
- ToNullPtr = CheckForNullPtr(ToExpr);
- }
-
- if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) {
- Tree.SetNode(FromExpr, ToExpr);
- Tree.SetDefault(FromIter.isEnd() && FromExpr,
- ToIter.isEnd() && ToExpr);
- if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) {
- if (FromExpr)
- HasFromInt = GetInt(FromIter, FromExpr, FromInt);
- if (ToExpr)
- HasToInt = GetInt(ToIter, ToExpr, ToInt);
- }
- if (HasFromInt && HasToInt) {
- Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
- Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
- Tree.SetKind(DiffTree::Integer);
- } else if (HasFromInt || HasToInt) {
- Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
- Tree.SetSame(false);
- Tree.SetKind(DiffTree::Integer);
- } else {
- Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr) ||
- (FromNullPtr && ToNullPtr));
- Tree.SetNullPtr(FromNullPtr, ToNullPtr);
- Tree.SetKind(DiffTree::Expression);
- }
- } else if (HasFromInt || HasToInt) {
- if (!HasFromInt && FromExpr)
- HasFromInt = GetInt(FromIter, FromExpr, FromInt);
- if (!HasToInt && ToExpr)
- HasToInt = GetInt(ToIter, ToExpr, ToInt);
- Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
- Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
- Tree.SetDefault(FromIter.isEnd() && HasFromInt,
- ToIter.isEnd() && HasToInt);
- Tree.SetKind(DiffTree::Integer);
- } else {
- if (!HasFromValueDecl && FromExpr)
- FromValueDecl = GetValueDecl(FromIter, FromExpr);
- if (!HasToValueDecl && ToExpr)
- ToValueDecl = GetValueDecl(ToIter, ToExpr);
- QualType ArgumentType = DefaultNTTPD->getType();
- bool FromAddressOf = false;
- if (FromValueDecl) {
- if (FromExpr) {
- if (UnaryOperator *UO =
- dyn_cast<UnaryOperator>(FromExpr->IgnoreParens())) {
- if (UO->getOpcode() == UO_AddrOf)
- FromAddressOf = true;
- }
- } else {
- if (!ArgumentType->isReferenceType()) {
- FromAddressOf = true;
- }
- }
- }
- bool ToAddressOf = false;
- if (ToValueDecl) {
- if (ToExpr) {
- if (UnaryOperator *UO =
- dyn_cast<UnaryOperator>(ToExpr->IgnoreParens())) {
- if (UO->getOpcode() == UO_AddrOf) {
- ToAddressOf = true;
- }
- }
- } else {
- if (!ArgumentType->isReferenceType()) {
- ToAddressOf = true;
- }
- }
- }
- Tree.SetNullPtr(FromNullPtr, ToNullPtr);
- Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
- Tree.SetSame(FromValueDecl && ToValueDecl &&
- FromValueDecl->getCanonicalDecl() ==
- ToValueDecl->getCanonicalDecl());
- Tree.SetDefault(FromIter.isEnd() && FromValueDecl,
- ToIter.isEnd() && ToValueDecl);
- Tree.SetKind(DiffTree::Declaration);
- }
- }
-
- // Handle Templates
- if (TemplateTemplateParmDecl *DefaultTTPD =
- dyn_cast<TemplateTemplateParmDecl>(ParamND)) {
- TemplateDecl *FromDecl, *ToDecl;
- FromDecl = GetTemplateDecl(FromIter, DefaultTTPD);
- ToDecl = GetTemplateDecl(ToIter, DefaultTTPD);
- Tree.SetNode(FromDecl, ToDecl);
- Tree.SetSame(
- FromDecl && ToDecl &&
- FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());
- Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl);
- Tree.SetKind(DiffTree::TemplateTemplate);
- }
+ unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);
+ unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1);
+ NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex);
+ NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex);
+
+ TemplateTypeParmDecl *FromDefaultTypeDecl =
+ dyn_cast<TemplateTypeParmDecl>(FromParamND);
+ TemplateTypeParmDecl *ToDefaultTypeDecl =
+ dyn_cast<TemplateTypeParmDecl>(ToParamND);
+ if (FromDefaultTypeDecl && ToDefaultTypeDecl)
+ DiffTypes(FromIter, ToIter, FromDefaultTypeDecl, ToDefaultTypeDecl);
+
+ TemplateTemplateParmDecl *FromDefaultTemplateDecl =
+ dyn_cast<TemplateTemplateParmDecl>(FromParamND);
+ TemplateTemplateParmDecl *ToDefaultTemplateDecl =
+ dyn_cast<TemplateTemplateParmDecl>(ToParamND);
+ if (FromDefaultTemplateDecl && ToDefaultTemplateDecl)
+ DiffTemplateTemplates(FromIter, ToIter, FromDefaultTemplateDecl,
+ ToDefaultTemplateDecl);
+
+ NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =
+ dyn_cast<NonTypeTemplateParmDecl>(FromParamND);
+ NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =
+ dyn_cast<NonTypeTemplateParmDecl>(ToParamND);
+ if (FromDefaultNonTypeDecl && ToDefaultNonTypeDecl)
+ DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,
+ ToDefaultNonTypeDecl);
++FromIter;
++ToIter;
@@ -1147,7 +1173,8 @@ class TemplateDiff {
/// GetType - Retrieves the template type arguments, including default
/// arguments.
- QualType GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD) {
+ static QualType GetType(const TSTiterator &Iter,
+ TemplateTypeParmDecl *DefaultTTPD) {
bool isVariadic = DefaultTTPD->isParameterPack();
if (!Iter.isEnd())
@@ -1164,7 +1191,8 @@ class TemplateDiff {
/// GetExpr - Retrieves the template expression argument, including default
/// arguments.
- Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) {
+ static Expr *GetExpr(const TSTiterator &Iter,
+ NonTypeTemplateParmDecl *DefaultNTTPD) {
Expr *ArgExpr = nullptr;
bool isVariadic = DefaultNTTPD->isParameterPack();
@@ -1183,7 +1211,8 @@ class TemplateDiff {
/// GetInt - Retrieves the template integer argument, including evaluating
/// default arguments.
- bool GetInt(const TSTiterator &Iter, Expr *ArgExpr, llvm::APInt &Int) {
+ static bool GetInt(ASTContext &Context, const TSTiterator &Iter,
+ Expr *ArgExpr, llvm::APInt &Int) {
// Default, value-depenedent expressions require fetching
// from the desugared TemplateArgument, otherwise expression needs to
// be evaluatable.
@@ -1209,7 +1238,7 @@ class TemplateDiff {
/// GetValueDecl - Retrieves the template Decl argument, including
/// default expression argument.
- ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
+ static ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
// Default, value-depenedent expressions require fetching
// from the desugared TemplateArgument
if (Iter.isEnd() && ArgExpr->isValueDependent())
@@ -1235,7 +1264,7 @@ class TemplateDiff {
/// CheckForNullPtr - returns true if the expression can be evaluated as
/// a null pointer
- bool CheckForNullPtr(Expr *E) {
+ static bool CheckForNullPtr(ASTContext &Context, Expr *E) {
assert(E && "Expected expression");
E = E->IgnoreParenCasts();
@@ -1256,7 +1285,7 @@ class TemplateDiff {
/// GetTemplateDecl - Retrieves the template template arguments, including
/// default arguments.
- TemplateDecl *GetTemplateDecl(const TSTiterator &Iter,
+ static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter,
TemplateTemplateParmDecl *DefaultTTPD) {
bool isVariadic = DefaultTTPD->isParameterPack();
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
index df7a2cb..ebf5e65 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
@@ -90,24 +91,22 @@ namespace {
class ASTDumper
: public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>,
- public ConstCommentVisitor<ASTDumper> {
+ public ConstCommentVisitor<ASTDumper>, public TypeVisitor<ASTDumper> {
raw_ostream &OS;
const CommandTraits *Traits;
const SourceManager *SM;
- bool IsFirstLine;
- // Indicates whether more child are expected at the current tree depth
- enum IndentType { IT_Child, IT_LastChild };
+ /// Pending[i] is an action to dump an entity at level i.
+ llvm::SmallVector<std::function<void(bool isLastChild)>, 32> Pending;
- /// Indents[i] indicates if another child exists at level i.
- /// Used by Indent() to print the tree structure.
- llvm::SmallVector<IndentType, 32> Indents;
+ /// Indicates whether we're at the top level.
+ bool TopLevel;
- /// Indicates that more children will be needed at this indent level.
- /// If true, prevents lastChild() from marking the node as the last child.
- /// This is used when there are multiple collections of children to be
- /// dumped as well as during conditional node dumping.
- bool MoreChildren;
+ /// Indicates if we're handling the first child after entering a new depth.
+ bool FirstChild;
+
+ /// Prefix for currently-being-dumped entity.
+ std::string Prefix;
/// Keep track of the last location we print out so that we can
/// print out deltas from then on out.
@@ -119,21 +118,70 @@ namespace {
bool ShowColors;
- class IndentScope {
- ASTDumper &Dumper;
- // Preserve the Dumper's MoreChildren value from the previous IndentScope
- bool MoreChildren;
- public:
- IndentScope(ASTDumper &Dumper) : Dumper(Dumper) {
- MoreChildren = Dumper.hasMoreChildren();
- Dumper.setMoreChildren(false);
- Dumper.indent();
+ /// Dump a child of the current node.
+ template<typename Fn> void dumpChild(Fn doDumpChild) {
+ // If we're at the top level, there's nothing interesting to do; just
+ // run the dumper.
+ if (TopLevel) {
+ TopLevel = false;
+ doDumpChild();
+ while (!Pending.empty()) {
+ Pending.back()(true);
+ Pending.pop_back();
+ }
+ Prefix.clear();
+ OS << "\n";
+ TopLevel = true;
+ return;
}
- ~IndentScope() {
- Dumper.setMoreChildren(MoreChildren);
- Dumper.unindent();
+
+ const FullComment *OrigFC = FC;
+ auto dumpWithIndent = [this, doDumpChild, OrigFC](bool isLastChild) {
+ // Print out the appropriate tree structure and work out the prefix for
+ // children of this node. For instance:
+ //
+ // A Prefix = ""
+ // |-B Prefix = "| "
+ // | `-C Prefix = "| "
+ // `-D Prefix = " "
+ // |-E Prefix = " | "
+ // `-F Prefix = " "
+ // G Prefix = ""
+ //
+ // Note that the first level gets no prefix.
+ {
+ OS << '\n';
+ ColorScope Color(*this, IndentColor);
+ OS << Prefix << (isLastChild ? '`' : '|') << '-';
+ this->Prefix.push_back(isLastChild ? ' ' : '|');
+ this->Prefix.push_back(' ');
+ }
+
+ FirstChild = true;
+ unsigned Depth = Pending.size();
+
+ FC = OrigFC;
+ doDumpChild();
+
+ // If any children are left, they're the last at their nesting level.
+ // Dump those ones out now.
+ while (Depth < Pending.size()) {
+ Pending.back()(true);
+ this->Pending.pop_back();
+ }
+
+ // Restore the old prefix.
+ this->Prefix.resize(Prefix.size() - 2);
+ };
+
+ if (FirstChild) {
+ Pending.push_back(std::move(dumpWithIndent));
+ } else {
+ Pending.back()(false);
+ Pending.back() = std::move(dumpWithIndent);
}
- };
+ FirstChild = false;
+ }
class ColorScope {
ASTDumper &Dumper;
@@ -149,78 +197,37 @@ namespace {
}
};
- class ChildDumper {
- ASTDumper &Dumper;
-
- const Decl *Prev;
- bool PrevRef;
- public:
- ChildDumper(ASTDumper &Dumper) : Dumper(Dumper), Prev(nullptr) {}
- ~ChildDumper() {
- if (Prev) {
- Dumper.lastChild();
- dump(nullptr);
- }
- }
-
- // FIXME: This should take an arbitrary callable as the dumping action.
- void dump(const Decl *D, bool Ref = false) {
- if (Prev) {
- if (PrevRef)
- Dumper.dumpDeclRef(Prev);
- else
- Dumper.dumpDecl(Prev);
- }
- Prev = D;
- PrevRef = Ref;
- }
- void dumpRef(const Decl *D) { dump(D, true); }
-
- // Give up ownership of the children of the node. By calling this,
- // the caller takes back responsibility for calling lastChild().
- void release() { dump(nullptr); }
- };
-
public:
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
const SourceManager *SM)
- : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false),
+ : OS(OS), Traits(Traits), SM(SM), TopLevel(true), FirstChild(true),
LastLocFilename(""), LastLocLine(~0U), FC(nullptr),
ShowColors(SM && SM->getDiagnostics().getShowColors()) { }
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
const SourceManager *SM, bool ShowColors)
- : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false),
+ : OS(OS), Traits(Traits), SM(SM), TopLevel(true), FirstChild(true),
LastLocFilename(""), LastLocLine(~0U),
ShowColors(ShowColors) { }
- ~ASTDumper() {
- OS << "\n";
- }
-
void dumpDecl(const Decl *D);
void dumpStmt(const Stmt *S);
void dumpFullComment(const FullComment *C);
- // Formatting
- void indent();
- void unindent();
- void lastChild();
- bool hasMoreChildren();
- void setMoreChildren(bool Value);
-
// Utilities
void dumpPointer(const void *Ptr);
void dumpSourceRange(SourceRange R);
void dumpLocation(SourceLocation Loc);
- void dumpBareType(QualType T);
+ void dumpBareType(QualType T, bool Desugar = true);
void dumpType(QualType T);
+ void dumpTypeAsChild(QualType T);
+ void dumpTypeAsChild(const Type *T);
void dumpBareDeclRef(const Decl *Node);
void dumpDeclRef(const Decl *Node, const char *Label = nullptr);
void dumpName(const NamedDecl *D);
bool hasNodes(const DeclContext *DC);
void dumpDeclContext(const DeclContext *DC);
- void dumpLookups(const DeclContext *DC);
+ void dumpLookups(const DeclContext *DC, bool DumpDecls);
void dumpAttr(const Attr *A);
// C++ Utilities
@@ -233,6 +240,175 @@ namespace {
void dumpTemplateArgument(const TemplateArgument &A,
SourceRange R = SourceRange());
+ // Types
+ void VisitComplexType(const ComplexType *T) {
+ dumpTypeAsChild(T->getElementType());
+ }
+ void VisitPointerType(const PointerType *T) {
+ dumpTypeAsChild(T->getPointeeType());
+ }
+ void VisitBlockPointerType(const BlockPointerType *T) {
+ dumpTypeAsChild(T->getPointeeType());
+ }
+ void VisitReferenceType(const ReferenceType *T) {
+ dumpTypeAsChild(T->getPointeeType());
+ }
+ void VisitRValueReferenceType(const ReferenceType *T) {
+ if (T->isSpelledAsLValue())
+ OS << " written as lvalue reference";
+ VisitReferenceType(T);
+ }
+ void VisitMemberPointerType(const MemberPointerType *T) {
+ dumpTypeAsChild(T->getClass());
+ dumpTypeAsChild(T->getPointeeType());
+ }
+ void VisitArrayType(const ArrayType *T) {
+ switch (T->getSizeModifier()) {
+ case ArrayType::Normal: break;
+ case ArrayType::Static: OS << " static"; break;
+ case ArrayType::Star: OS << " *"; break;
+ }
+ OS << " " << T->getIndexTypeQualifiers().getAsString();
+ dumpTypeAsChild(T->getElementType());
+ }
+ void VisitConstantArrayType(const ConstantArrayType *T) {
+ OS << " " << T->getSize();
+ VisitArrayType(T);
+ }
+ void VisitVariableArrayType(const VariableArrayType *T) {
+ OS << " ";
+ dumpSourceRange(T->getBracketsRange());
+ VisitArrayType(T);
+ dumpStmt(T->getSizeExpr());
+ }
+ void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
+ VisitArrayType(T);
+ OS << " ";
+ dumpSourceRange(T->getBracketsRange());
+ dumpStmt(T->getSizeExpr());
+ }
+ void VisitDependentSizedExtVectorType(
+ const DependentSizedExtVectorType *T) {
+ OS << " ";
+ dumpLocation(T->getAttributeLoc());
+ dumpTypeAsChild(T->getElementType());
+ dumpStmt(T->getSizeExpr());
+ }
+ void VisitVectorType(const VectorType *T) {
+ switch (T->getVectorKind()) {
+ case VectorType::GenericVector: break;
+ case VectorType::AltiVecVector: OS << " altivec"; break;
+ case VectorType::AltiVecPixel: OS << " altivec pixel"; break;
+ case VectorType::AltiVecBool: OS << " altivec bool"; break;
+ case VectorType::NeonVector: OS << " neon"; break;
+ case VectorType::NeonPolyVector: OS << " neon poly"; break;
+ }
+ OS << " " << T->getNumElements();
+ dumpTypeAsChild(T->getElementType());
+ }
+ void VisitFunctionType(const FunctionType *T) {
+ auto EI = T->getExtInfo();
+ if (EI.getNoReturn()) OS << " noreturn";
+ if (EI.getProducesResult()) OS << " produces_result";
+ if (EI.getHasRegParm()) OS << " regparm " << EI.getRegParm();
+ OS << " " << FunctionType::getNameForCallConv(EI.getCC());
+ dumpTypeAsChild(T->getReturnType());
+ }
+ void VisitFunctionProtoType(const FunctionProtoType *T) {
+ auto EPI = T->getExtProtoInfo();
+ if (EPI.HasTrailingReturn) OS << " trailing_return";
+ if (T->isConst()) OS << " const";
+ if (T->isVolatile()) OS << " volatile";
+ if (T->isRestrict()) OS << " restrict";
+ switch (EPI.RefQualifier) {
+ case RQ_None: break;
+ case RQ_LValue: OS << " &"; break;
+ case RQ_RValue: OS << " &&"; break;
+ }
+ // FIXME: Exception specification.
+ // FIXME: Consumed parameters.
+ VisitFunctionType(T);
+ for (QualType PT : T->getParamTypes())
+ dumpTypeAsChild(PT);
+ if (EPI.Variadic)
+ dumpChild([=] { OS << "..."; });
+ }
+ void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+ dumpDeclRef(T->getDecl());
+ }
+ void VisitTypedefType(const TypedefType *T) {
+ dumpDeclRef(T->getDecl());
+ }
+ void VisitTypeOfExprType(const TypeOfExprType *T) {
+ dumpStmt(T->getUnderlyingExpr());
+ }
+ void VisitDecltypeType(const DecltypeType *T) {
+ dumpStmt(T->getUnderlyingExpr());
+ }
+ void VisitUnaryTransformType(const UnaryTransformType *T) {
+ switch (T->getUTTKind()) {
+ case UnaryTransformType::EnumUnderlyingType:
+ OS << " underlying_type";
+ break;
+ }
+ dumpTypeAsChild(T->getBaseType());
+ }
+ void VisitTagType(const TagType *T) {
+ dumpDeclRef(T->getDecl());
+ }
+ void VisitAttributedType(const AttributedType *T) {
+ // FIXME: AttrKind
+ dumpTypeAsChild(T->getModifiedType());
+ }
+ void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+ OS << " depth " << T->getDepth() << " index " << T->getIndex();
+ if (T->isParameterPack()) OS << " pack";
+ dumpDeclRef(T->getDecl());
+ }
+ void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
+ dumpTypeAsChild(T->getReplacedParameter());
+ }
+ void VisitSubstTemplateTypeParmPackType(
+ const SubstTemplateTypeParmPackType *T) {
+ dumpTypeAsChild(T->getReplacedParameter());
+ dumpTemplateArgument(T->getArgumentPack());
+ }
+ void VisitAutoType(const AutoType *T) {
+ if (T->isDecltypeAuto()) OS << " decltype(auto)";
+ if (!T->isDeduced())
+ OS << " undeduced";
+ }
+ void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
+ if (T->isTypeAlias()) OS << " alias";
+ OS << " "; T->getTemplateName().dump(OS);
+ for (auto &Arg : *T)
+ dumpTemplateArgument(Arg);
+ if (T->isTypeAlias())
+ dumpTypeAsChild(T->getAliasedType());
+ }
+ void VisitInjectedClassNameType(const InjectedClassNameType *T) {
+ dumpDeclRef(T->getDecl());
+ }
+ void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+ dumpDeclRef(T->getDecl());
+ }
+ void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ dumpTypeAsChild(T->getPointeeType());
+ }
+ void VisitAtomicType(const AtomicType *T) {
+ dumpTypeAsChild(T->getValueType());
+ }
+ void VisitAdjustedType(const AdjustedType *T) {
+ dumpTypeAsChild(T->getOriginalType());
+ }
+ void VisitPackExpansionType(const PackExpansionType *T) {
+ if (auto N = T->getNumExpansions()) OS << " expansions " << *N;
+ if (!T->isSugared())
+ dumpTypeAsChild(T->getPattern());
+ }
+ // FIXME: ElaboratedType, DependentNameType,
+ // DependentTemplateSpecializationType, ObjCObjectType
+
// Decls
void VisitLabelDecl(const LabelDecl *D);
void VisitTypedefDecl(const TypedefDecl *D);
@@ -255,8 +431,7 @@ namespace {
void VisitCXXRecordDecl(const CXXRecordDecl *D);
void VisitStaticAssertDecl(const StaticAssertDecl *D);
template<typename SpecializationDecl>
- void VisitTemplateDeclSpecialization(ChildDumper &Children,
- const SpecializationDecl *D,
+ void VisitTemplateDeclSpecialization(const SpecializationDecl *D,
bool DumpExplicitInst,
bool DumpRefOnly);
template<typename TemplateDecl>
@@ -378,67 +553,6 @@ namespace {
// Utilities
//===----------------------------------------------------------------------===//
-// Print out the appropriate tree structure using the Indents vector.
-// Example of tree and the Indents vector at each level.
-// A { }
-// |-B { IT_Child }
-// | `-C { IT_Child, IT_LastChild }
-// `-D { IT_LastChild }
-// |-E { IT_LastChild, IT_Child }
-// `-F { IT_LastChild, IT_LastChild }
-// Type non-last element, last element
-// IT_Child "| " "|-"
-// IT_LastChild " " "`-"
-void ASTDumper::indent() {
- if (IsFirstLine)
- IsFirstLine = false;
- else
- OS << "\n";
-
- ColorScope Color(*this, IndentColor);
- for (SmallVectorImpl<IndentType>::const_iterator I = Indents.begin(),
- E = Indents.end();
- I != E; ++I) {
- switch (*I) {
- case IT_Child:
- if (I == E - 1)
- OS << "|-";
- else
- OS << "| ";
- continue;
- case IT_LastChild:
- if (I == E - 1)
- OS << "`-";
- else
- OS << " ";
- continue;
- }
- llvm_unreachable("Invalid IndentType");
- }
- Indents.push_back(IT_Child);
-}
-
-void ASTDumper::unindent() {
- Indents.pop_back();
-}
-
-// Call before each potential last child node is to be dumped. If MoreChildren
-// is false, then this is the last child, otherwise treat as a regular node.
-void ASTDumper::lastChild() {
- if (!hasMoreChildren())
- Indents.back() = IT_LastChild;
-}
-
-// MoreChildren should be set before calling another function that may print
-// additional nodes to prevent conflicting final child nodes.
-bool ASTDumper::hasMoreChildren() {
- return MoreChildren;
-}
-
-void ASTDumper::setMoreChildren(bool Value) {
- MoreChildren = Value;
-}
-
void ASTDumper::dumpPointer(const void *Ptr) {
ColorScope Color(*this, AddressColor);
OS << ' ' << Ptr;
@@ -491,13 +605,13 @@ void ASTDumper::dumpSourceRange(SourceRange R) {
}
-void ASTDumper::dumpBareType(QualType T) {
+void ASTDumper::dumpBareType(QualType T, bool Desugar) {
ColorScope Color(*this, TypeColor);
-
+
SplitQualType T_split = T.split();
OS << "'" << QualType::getAsString(T_split) << "'";
- if (!T.isNull()) {
+ if (Desugar && !T.isNull()) {
// If the type is sugared, also dump a (shallow) desugared type.
SplitQualType D_split = T.getSplitDesugaredType();
if (T_split != D_split)
@@ -510,6 +624,59 @@ void ASTDumper::dumpType(QualType T) {
dumpBareType(T);
}
+void ASTDumper::dumpTypeAsChild(QualType T) {
+ SplitQualType SQT = T.split();
+ if (!SQT.Quals.hasQualifiers())
+ return dumpTypeAsChild(SQT.Ty);
+
+ dumpChild([=] {
+ OS << "QualType";
+ dumpPointer(T.getAsOpaquePtr());
+ OS << " ";
+ dumpBareType(T, false);
+ OS << " " << T.split().Quals.getAsString();
+ dumpTypeAsChild(T.split().Ty);
+ });
+}
+
+void ASTDumper::dumpTypeAsChild(const Type *T) {
+ dumpChild([=] {
+ if (!T) {
+ ColorScope Color(*this, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
+
+ {
+ ColorScope Color(*this, TypeColor);
+ OS << T->getTypeClassName() << "Type";
+ }
+ dumpPointer(T);
+ OS << " ";
+ dumpBareType(QualType(T, 0), false);
+
+ QualType SingleStepDesugar =
+ T->getLocallyUnqualifiedSingleStepDesugaredType();
+ if (SingleStepDesugar != QualType(T, 0))
+ OS << " sugar";
+ if (T->isDependentType())
+ OS << " dependent";
+ else if (T->isInstantiationDependentType())
+ OS << " instantiation_dependent";
+ if (T->isVariablyModifiedType())
+ OS << " variably_modified";
+ if (T->containsUnexpandedParameterPack())
+ OS << " contains_unexpanded_pack";
+ if (T->isFromAST())
+ OS << " imported";
+
+ TypeVisitor<ASTDumper>::Visit(T);
+
+ if (SingleStepDesugar != QualType(T, 0))
+ dumpTypeAsChild(SingleStepDesugar);
+ });
+}
+
void ASTDumper::dumpBareDeclRef(const Decl *D) {
{
ColorScope Color(*this, DeclKindNameColor);
@@ -530,10 +697,11 @@ void ASTDumper::dumpDeclRef(const Decl *D, const char *Label) {
if (!D)
return;
- IndentScope Indent(*this);
- if (Label)
- OS << Label << ' ';
- dumpBareDeclRef(D);
+ dumpChild([=]{
+ if (Label)
+ OS << Label << ' ';
+ dumpBareDeclRef(D);
+ });
}
void ASTDumper::dumpName(const NamedDecl *ND) {
@@ -555,86 +723,96 @@ void ASTDumper::dumpDeclContext(const DeclContext *DC) {
if (!DC)
return;
- ChildDumper Children(*this);
for (auto *D : DC->noload_decls())
- Children.dump(D);
+ dumpDecl(D);
if (DC->hasExternalLexicalStorage()) {
- Children.release();
-
- lastChild();
- IndentScope Indent(*this);
- ColorScope Color(*this, UndeserializedColor);
- OS << "<undeserialized declarations>";
+ dumpChild([=]{
+ ColorScope Color(*this, UndeserializedColor);
+ OS << "<undeserialized declarations>";
+ });
}
}
-void ASTDumper::dumpLookups(const DeclContext *DC) {
- IndentScope Indent(*this);
+void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
+ dumpChild([=] {
+ OS << "StoredDeclsMap ";
+ dumpBareDeclRef(cast<Decl>(DC));
- OS << "StoredDeclsMap ";
- dumpBareDeclRef(cast<Decl>(DC));
+ const DeclContext *Primary = DC->getPrimaryContext();
+ if (Primary != DC) {
+ OS << " primary";
+ dumpPointer(cast<Decl>(Primary));
+ }
- const DeclContext *Primary = DC->getPrimaryContext();
- if (Primary != DC) {
- OS << " primary";
- dumpPointer(cast<Decl>(Primary));
- }
+ bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
- bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
+ DeclContext::all_lookups_iterator I = Primary->noload_lookups_begin(),
+ E = Primary->noload_lookups_end();
+ while (I != E) {
+ DeclarationName Name = I.getLookupName();
+ DeclContextLookupResult R = *I++;
- DeclContext::all_lookups_iterator I = Primary->noload_lookups_begin(),
- E = Primary->noload_lookups_end();
- while (I != E) {
- DeclarationName Name = I.getLookupName();
- DeclContextLookupResult R = *I++;
- if (I == E && !HasUndeserializedLookups)
- lastChild();
+ dumpChild([=] {
+ OS << "DeclarationName ";
+ {
+ ColorScope Color(*this, DeclNameColor);
+ OS << '\'' << Name << '\'';
+ }
- IndentScope Indent(*this);
- OS << "DeclarationName ";
- {
- ColorScope Color(*this, DeclNameColor);
- OS << '\'' << Name << '\'';
+ for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
+ RI != RE; ++RI) {
+ dumpChild([=] {
+ dumpBareDeclRef(*RI);
+
+ if ((*RI)->isHidden())
+ OS << " hidden";
+
+ // If requested, dump the redecl chain for this lookup.
+ if (DumpDecls) {
+ // Dump earliest decl first.
+ std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
+ if (Decl *Prev = D->getPreviousDecl())
+ DumpWithPrev(Prev);
+ dumpDecl(D);
+ };
+ DumpWithPrev(*RI);
+ }
+ });
+ }
+ });
}
- for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
- RI != RE; ++RI) {
- if (RI + 1 == RE)
- lastChild();
- dumpDeclRef(*RI);
- if ((*RI)->isHidden())
- OS << " hidden";
+ if (HasUndeserializedLookups) {
+ dumpChild([=] {
+ ColorScope Color(*this, UndeserializedColor);
+ OS << "<undeserialized lookups>";
+ });
}
- }
-
- if (HasUndeserializedLookups) {
- lastChild();
- IndentScope Indent(*this);
- ColorScope Color(*this, UndeserializedColor);
- OS << "<undeserialized lookups>";
- }
+ });
}
void ASTDumper::dumpAttr(const Attr *A) {
- IndentScope Indent(*this);
- {
- ColorScope Color(*this, AttrColor);
+ dumpChild([=] {
+ {
+ ColorScope Color(*this, AttrColor);
- switch (A->getKind()) {
+ switch (A->getKind()) {
#define ATTR(X) case attr::X: OS << #X; break;
#include "clang/Basic/AttrList.inc"
- default: llvm_unreachable("unexpected attribute kind");
+ default:
+ llvm_unreachable("unexpected attribute kind");
+ }
+ OS << "Attr";
}
- OS << "Attr";
- }
- dumpPointer(A);
- dumpSourceRange(A->getRange());
- if (A->isInherited())
- OS << " Inherited";
- if (A->isImplicit())
- OS << " Implicit";
+ dumpPointer(A);
+ dumpSourceRange(A->getRange());
+ if (A->isInherited())
+ OS << " Inherited";
+ if (A->isImplicit())
+ OS << " Implicit";
#include "clang/AST/AttrDump.inc"
+ });
}
static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
@@ -687,15 +865,20 @@ void ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) {
}
void ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) {
- IndentScope Indent(*this);
- OS << "CXXCtorInitializer";
- if (Init->isAnyMemberInitializer()) {
- OS << ' ';
- dumpBareDeclRef(Init->getAnyMember());
- } else {
- dumpType(QualType(Init->getBaseClass(), 0));
- }
- dumpStmt(Init->getInit());
+ dumpChild([=] {
+ OS << "CXXCtorInitializer";
+ if (Init->isAnyMemberInitializer()) {
+ OS << ' ';
+ dumpBareDeclRef(Init->getAnyMember());
+ } else if (Init->isBaseInitializer()) {
+ dumpType(QualType(Init->getBaseClass(), 0));
+ } else if (Init->isDelegatingInitializer()) {
+ dumpType(Init->getTypeSourceInfo()->getType());
+ } else {
+ llvm_unreachable("Unknown initializer type");
+ }
+ dumpStmt(Init->getInit());
+ });
}
void ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) {
@@ -709,11 +892,8 @@ void ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) {
void ASTDumper::dumpTemplateArgumentListInfo(
const TemplateArgumentListInfo &TALI) {
- for (unsigned i = 0, e = TALI.size(); i < e; ++i) {
- if (i + 1 == e)
- lastChild();
+ for (unsigned i = 0, e = TALI.size(); i < e; ++i)
dumpTemplateArgumentLoc(TALI[i]);
- }
}
void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) {
@@ -726,54 +906,49 @@ void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) {
}
void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) {
- IndentScope Indent(*this);
- OS << "TemplateArgument";
- if (R.isValid())
- dumpSourceRange(R);
-
- switch (A.getKind()) {
- case TemplateArgument::Null:
- OS << " null";
- break;
- case TemplateArgument::Type:
- OS << " type";
- lastChild();
- dumpType(A.getAsType());
- break;
- case TemplateArgument::Declaration:
- OS << " decl";
- lastChild();
- dumpDeclRef(A.getAsDecl());
- break;
- case TemplateArgument::NullPtr:
- OS << " nullptr";
- break;
- case TemplateArgument::Integral:
- OS << " integral " << A.getAsIntegral();
- break;
- case TemplateArgument::Template:
- OS << " template ";
- A.getAsTemplate().dump(OS);
- break;
- case TemplateArgument::TemplateExpansion:
- OS << " template expansion";
- A.getAsTemplateOrTemplatePattern().dump(OS);
- break;
- case TemplateArgument::Expression:
- OS << " expr";
- lastChild();
- dumpStmt(A.getAsExpr());
- break;
- case TemplateArgument::Pack:
- OS << " pack";
- for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
- dumpTemplateArgument(*I);
+ dumpChild([=] {
+ OS << "TemplateArgument";
+ if (R.isValid())
+ dumpSourceRange(R);
+
+ switch (A.getKind()) {
+ case TemplateArgument::Null:
+ OS << " null";
+ break;
+ case TemplateArgument::Type:
+ OS << " type";
+ dumpType(A.getAsType());
+ break;
+ case TemplateArgument::Declaration:
+ OS << " decl";
+ dumpDeclRef(A.getAsDecl());
+ break;
+ case TemplateArgument::NullPtr:
+ OS << " nullptr";
+ break;
+ case TemplateArgument::Integral:
+ OS << " integral " << A.getAsIntegral();
+ break;
+ case TemplateArgument::Template:
+ OS << " template ";
+ A.getAsTemplate().dump(OS);
+ break;
+ case TemplateArgument::TemplateExpansion:
+ OS << " template expansion";
+ A.getAsTemplateOrTemplatePattern().dump(OS);
+ break;
+ case TemplateArgument::Expression:
+ OS << " expr";
+ dumpStmt(A.getAsExpr());
+ break;
+ case TemplateArgument::Pack:
+ OS << " pack";
+ for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end();
+ I != E; ++I)
+ dumpTemplateArgument(*I);
+ break;
}
- break;
- }
+ });
}
//===----------------------------------------------------------------------===//
@@ -781,64 +956,57 @@ void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) {
//===----------------------------------------------------------------------===//
void ASTDumper::dumpDecl(const Decl *D) {
- IndentScope Indent(*this);
+ dumpChild([=] {
+ if (!D) {
+ ColorScope Color(*this, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
- if (!D) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>>";
- return;
- }
+ {
+ ColorScope Color(*this, DeclKindNameColor);
+ OS << D->getDeclKindName() << "Decl";
+ }
+ dumpPointer(D);
+ if (D->getLexicalDeclContext() != D->getDeclContext())
+ OS << " parent " << cast<Decl>(D->getDeclContext());
+ dumpPreviousDecl(OS, D);
+ dumpSourceRange(D->getSourceRange());
+ OS << ' ';
+ dumpLocation(D->getLocation());
+ if (Module *M = D->getOwningModule())
+ OS << " in " << M->getFullModuleName();
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (ND->isHidden())
+ OS << " hidden";
+ if (D->isImplicit())
+ OS << " implicit";
+ if (D->isUsed())
+ OS << " used";
+ else if (D->isThisDeclarationReferenced())
+ OS << " referenced";
+ if (D->isInvalidDecl())
+ OS << " invalid";
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isConstexpr())
+ OS << " constexpr";
- {
- ColorScope Color(*this, DeclKindNameColor);
- OS << D->getDeclKindName() << "Decl";
- }
- dumpPointer(D);
- if (D->getLexicalDeclContext() != D->getDeclContext())
- OS << " parent " << cast<Decl>(D->getDeclContext());
- dumpPreviousDecl(OS, D);
- dumpSourceRange(D->getSourceRange());
- OS << ' ';
- dumpLocation(D->getLocation());
- if (Module *M = D->getOwningModule())
- OS << " in " << M->getFullModuleName();
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- if (ND->isHidden())
- OS << " hidden";
- if (D->isImplicit())
- OS << " implicit";
- if (D->isUsed())
- OS << " used";
- else if (D->isReferenced())
- OS << " referenced";
- if (D->isInvalidDecl())
- OS << " invalid";
-
- bool HasAttrs = D->hasAttrs();
- const FullComment *Comment =
- D->getASTContext().getLocalCommentForDeclUncached(D);
- // Decls within functions are visited by the body
- bool HasDeclContext = !isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) &&
- hasNodes(dyn_cast<DeclContext>(D));
-
- setMoreChildren(HasAttrs || Comment || HasDeclContext);
- ConstDeclVisitor<ASTDumper>::Visit(D);
-
- setMoreChildren(Comment || HasDeclContext);
- for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
- dumpAttr(*I);
- }
- setMoreChildren(HasDeclContext);
- lastChild();
- dumpFullComment(Comment);
+ ConstDeclVisitor<ASTDumper>::Visit(D);
- setMoreChildren(false);
- if (HasDeclContext)
- dumpDeclContext(cast<DeclContext>(D));
+ for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); I != E;
+ ++I)
+ dumpAttr(*I);
+
+ if (const FullComment *Comment =
+ D->getASTContext().getLocalCommentForDeclUncached(D))
+ dumpFullComment(Comment);
+
+ // Decls within functions are visited by the body.
+ if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) &&
+ hasNodes(dyn_cast<DeclContext>(D)))
+ dumpDeclContext(cast<DeclContext>(D));
+ });
}
void ASTDumper::VisitLabelDecl(const LabelDecl *D) {
@@ -878,19 +1046,16 @@ void ASTDumper::VisitRecordDecl(const RecordDecl *D) {
void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) {
dumpName(D);
dumpType(D->getType());
- if (const Expr *Init = D->getInitExpr()) {
- lastChild();
+ if (const Expr *Init = D->getInitExpr())
dumpStmt(Init);
- }
}
void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) {
dumpName(D);
dumpType(D->getType());
- ChildDumper Children(*this);
for (auto *Child : D->chain())
- Children.dumpRef(Child);
+ dumpDeclRef(Child);
}
void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
@@ -914,73 +1079,39 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- switch (EPI.ExceptionSpecType) {
+ switch (EPI.ExceptionSpec.Type) {
default: break;
case EST_Unevaluated:
- OS << " noexcept-unevaluated " << EPI.ExceptionSpecDecl;
+ OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl;
break;
case EST_Uninstantiated:
- OS << " noexcept-uninstantiated " << EPI.ExceptionSpecTemplate;
+ OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate;
break;
}
}
- bool OldMoreChildren = hasMoreChildren();
- const FunctionTemplateSpecializationInfo *FTSI =
- D->getTemplateSpecializationInfo();
- bool HasTemplateSpecialization = FTSI;
-
- bool HasNamedDecls = D->getDeclsInPrototypeScope().begin() !=
- D->getDeclsInPrototypeScope().end();
-
- bool HasFunctionDecls = D->param_begin() != D->param_end();
-
- const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D);
- bool HasCtorInitializers = C && C->init_begin() != C->init_end();
-
- bool HasDeclarationBody = D->doesThisDeclarationHaveABody();
-
- setMoreChildren(OldMoreChildren || HasNamedDecls || HasFunctionDecls ||
- HasCtorInitializers || HasDeclarationBody);
- if (HasTemplateSpecialization) {
- lastChild();
+ if (const FunctionTemplateSpecializationInfo *FTSI =
+ D->getTemplateSpecializationInfo())
dumpTemplateArgumentList(*FTSI->TemplateArguments);
- }
- setMoreChildren(OldMoreChildren || HasFunctionDecls ||
- HasCtorInitializers || HasDeclarationBody);
for (ArrayRef<NamedDecl *>::iterator
I = D->getDeclsInPrototypeScope().begin(),
- E = D->getDeclsInPrototypeScope().end(); I != E; ++I) {
- if (I + 1 == E)
- lastChild();
+ E = D->getDeclsInPrototypeScope().end(); I != E; ++I)
dumpDecl(*I);
- }
- setMoreChildren(OldMoreChildren || HasCtorInitializers || HasDeclarationBody);
for (FunctionDecl::param_const_iterator I = D->param_begin(),
E = D->param_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
+ I != E; ++I)
dumpDecl(*I);
- }
-
- setMoreChildren(OldMoreChildren || HasDeclarationBody);
- if (HasCtorInitializers)
+
+ if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D))
for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
E = C->init_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
+ I != E; ++I)
dumpCXXCtorInitializer(*I);
- }
- setMoreChildren(OldMoreChildren);
- if (HasDeclarationBody) {
- lastChild();
+ if (D->doesThisDeclarationHaveABody())
dumpStmt(D->getBody());
- }
}
void ASTDumper::VisitFieldDecl(const FieldDecl *D) {
@@ -991,21 +1122,10 @@ void ASTDumper::VisitFieldDecl(const FieldDecl *D) {
if (D->isModulePrivate())
OS << " __module_private__";
- bool OldMoreChildren = hasMoreChildren();
- bool IsBitField = D->isBitField();
- Expr *Init = D->getInClassInitializer();
- bool HasInit = Init;
-
- setMoreChildren(OldMoreChildren || HasInit);
- if (IsBitField) {
- lastChild();
+ if (D->isBitField())
dumpStmt(D->getBitWidth());
- }
- setMoreChildren(OldMoreChildren);
- if (HasInit) {
- lastChild();
+ if (Expr *Init = D->getInClassInitializer())
dumpStmt(Init);
- }
}
void ASTDumper::VisitVarDecl(const VarDecl *D) {
@@ -1029,13 +1149,11 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) {
case VarDecl::CallInit: OS << " callinit"; break;
case VarDecl::ListInit: OS << " listinit"; break;
}
- lastChild();
dumpStmt(D->getInit());
}
}
void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) {
- lastChild();
dumpStmt(D->getAsmString());
}
@@ -1082,25 +1200,24 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
return;
for (const auto &I : D->bases()) {
- IndentScope Indent(*this);
- if (I.isVirtual())
- OS << "virtual ";
- dumpAccessSpecifier(I.getAccessSpecifier());
- dumpType(I.getType());
- if (I.isPackExpansion())
- OS << "...";
+ dumpChild([=] {
+ if (I.isVirtual())
+ OS << "virtual ";
+ dumpAccessSpecifier(I.getAccessSpecifier());
+ dumpType(I.getType());
+ if (I.isPackExpansion())
+ OS << "...";
+ });
}
}
void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) {
dumpStmt(D->getAssertExpr());
- lastChild();
dumpStmt(D->getMessage());
}
template<typename SpecializationDecl>
-void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children,
- const SpecializationDecl *D,
+void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D,
bool DumpExplicitInst,
bool DumpRefOnly) {
bool DumpedAny = false;
@@ -1125,7 +1242,10 @@ void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children,
// Fall through.
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
- Children.dump(Redecl, DumpRefOnly);
+ if (DumpRefOnly)
+ dumpDeclRef(Redecl);
+ else
+ dumpDecl(Redecl);
DumpedAny = true;
break;
case TSK_ExplicitSpecialization:
@@ -1135,7 +1255,7 @@ void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children,
// Ensure we dump at least one decl for each specialization.
if (!DumpedAny)
- Children.dumpRef(D);
+ dumpDeclRef(D);
}
template<typename TemplateDecl>
@@ -1144,11 +1264,10 @@ void ASTDumper::VisitTemplateDecl(const TemplateDecl *D,
dumpName(D);
dumpTemplateParameters(D->getTemplateParameters());
- ChildDumper Children(*this);
- Children.dump(D->getTemplatedDecl());
+ dumpDecl(D->getTemplatedDecl());
for (auto *Child : D->specializations())
- VisitTemplateDeclSpecialization(Children, Child, DumpExplicitInst,
+ VisitTemplateDeclSpecialization(Child, DumpExplicitInst,
!D->isCanonicalDecl());
}
@@ -1206,10 +1325,8 @@ void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
if (D->isParameterPack())
OS << " ...";
dumpName(D);
- if (D->hasDefaultArgument()) {
- lastChild();
+ if (D->hasDefaultArgument())
dumpTemplateArgument(D->getDefaultArgument());
- }
}
void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
@@ -1217,10 +1334,8 @@ void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
if (D->isParameterPack())
OS << " ...";
dumpName(D);
- if (D->hasDefaultArgument()) {
- lastChild();
+ if (D->hasDefaultArgument())
dumpTemplateArgument(D->getDefaultArgument());
- }
}
void ASTDumper::VisitTemplateTemplateParmDecl(
@@ -1229,10 +1344,8 @@ void ASTDumper::VisitTemplateTemplateParmDecl(
OS << " ...";
dumpName(D);
dumpTemplateParameters(D->getTemplateParameters());
- if (D->hasDefaultArgument()) {
- lastChild();
+ if (D->hasDefaultArgument())
dumpTemplateArgumentLoc(D->getDefaultArgument());
- }
}
void ASTDumper::VisitUsingDecl(const UsingDecl *D) {
@@ -1273,7 +1386,6 @@ void ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) {
}
void ASTDumper::VisitFriendDecl(const FriendDecl *D) {
- lastChild();
if (TypeSourceInfo *T = D->getFriendType())
dumpType(T->getType());
else
@@ -1317,96 +1429,66 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
dumpName(D);
dumpType(D->getReturnType());
- bool OldMoreChildren = hasMoreChildren();
- bool IsVariadic = D->isVariadic();
- bool HasBody = D->hasBody();
-
- setMoreChildren(OldMoreChildren || IsVariadic || HasBody);
if (D->isThisDeclarationADefinition()) {
- lastChild();
dumpDeclContext(D);
} else {
for (ObjCMethodDecl::param_const_iterator I = D->param_begin(),
E = D->param_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
+ I != E; ++I)
dumpDecl(*I);
- }
}
- setMoreChildren(OldMoreChildren || HasBody);
- if (IsVariadic) {
- lastChild();
- IndentScope Indent(*this);
- OS << "...";
- }
+ if (D->isVariadic())
+ dumpChild([=] { OS << "..."; });
- setMoreChildren(OldMoreChildren);
- if (HasBody) {
- lastChild();
+ if (D->hasBody())
dumpStmt(D->getBody());
- }
}
void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
dumpName(D);
dumpDeclRef(D->getClassInterface());
- if (D->protocol_begin() == D->protocol_end())
- lastChild();
dumpDeclRef(D->getImplementation());
for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(),
E = D->protocol_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
+ I != E; ++I)
dumpDeclRef(*I);
- }
}
void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
dumpName(D);
dumpDeclRef(D->getClassInterface());
- lastChild();
dumpDeclRef(D->getCategoryDecl());
}
void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
dumpName(D);
- ChildDumper Children(*this);
for (auto *Child : D->protocols())
- Children.dumpRef(Child);
+ dumpDeclRef(Child);
}
void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
dumpName(D);
dumpDeclRef(D->getSuperClass(), "super");
- ChildDumper Children(*this);
- Children.dumpRef(D->getImplementation());
+ dumpDeclRef(D->getImplementation());
for (auto *Child : D->protocols())
- Children.dumpRef(Child);
+ dumpDeclRef(Child);
}
void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
dumpName(D);
dumpDeclRef(D->getSuperClass(), "super");
- if (D->init_begin() == D->init_end())
- lastChild();
dumpDeclRef(D->getClassInterface());
for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(),
E = D->init_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
+ I != E; ++I)
dumpCXXCtorInitializer(*I);
- }
}
void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) {
dumpName(D);
- lastChild();
dumpDeclRef(D->getClassInterface());
}
@@ -1441,15 +1523,10 @@ void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
OS << " strong";
if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained)
OS << " unsafe_unretained";
- if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) {
- if (!(Attrs & ObjCPropertyDecl::OBJC_PR_setter))
- lastChild();
+ if (Attrs & ObjCPropertyDecl::OBJC_PR_getter)
dumpDeclRef(D->getGetterMethodDecl(), "getter");
- }
- if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) {
- lastChild();
+ if (Attrs & ObjCPropertyDecl::OBJC_PR_setter)
dumpDeclRef(D->getSetterMethodDecl(), "setter");
- }
}
}
@@ -1460,7 +1537,6 @@ void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
else
OS << " dynamic";
dumpDeclRef(D->getPropertyDecl());
- lastChild();
dumpDeclRef(D->getPropertyIvarDecl());
}
@@ -1468,30 +1544,27 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) {
for (auto I : D->params())
dumpDecl(I);
- if (D->isVariadic()) {
- IndentScope Indent(*this);
- OS << "...";
- }
+ if (D->isVariadic())
+ dumpChild([=]{ OS << "..."; });
+
+ if (D->capturesCXXThis())
+ dumpChild([=]{ OS << "capture this"; });
- if (D->capturesCXXThis()) {
- IndentScope Indent(*this);
- OS << "capture this";
- }
for (const auto &I : D->captures()) {
- IndentScope Indent(*this);
- OS << "capture";
- if (I.isByRef())
- OS << " byref";
- if (I.isNested())
- OS << " nested";
- if (I.getVariable()) {
- OS << ' ';
- dumpBareDeclRef(I.getVariable());
- }
- if (I.hasCopyExpr())
- dumpStmt(I.getCopyExpr());
+ dumpChild([=] {
+ OS << "capture";
+ if (I.isByRef())
+ OS << " byref";
+ if (I.isNested())
+ OS << " nested";
+ if (I.getVariable()) {
+ OS << ' ';
+ dumpBareDeclRef(I.getVariable());
+ }
+ if (I.hasCopyExpr())
+ dumpStmt(I.getCopyExpr());
+ });
}
- lastChild();
dumpStmt(D->getBody());
}
@@ -1500,29 +1573,23 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) {
//===----------------------------------------------------------------------===//
void ASTDumper::dumpStmt(const Stmt *S) {
- IndentScope Indent(*this);
+ dumpChild([=] {
+ if (!S) {
+ ColorScope Color(*this, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
- if (!S) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>>";
- return;
- }
+ if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+ VisitDeclStmt(DS);
+ return;
+ }
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
- VisitDeclStmt(DS);
- return;
- }
+ ConstStmtVisitor<ASTDumper>::Visit(S);
- setMoreChildren(!S->children().empty());
- ConstStmtVisitor<ASTDumper>::Visit(S);
- setMoreChildren(false);
- for (Stmt::const_child_range CI = S->children(); CI; ++CI) {
- Stmt::const_child_range Next = CI;
- ++Next;
- if (!Next)
- lastChild();
- dumpStmt(*CI);
- }
+ for (Stmt::const_child_range CI = S->children(); CI; ++CI)
+ dumpStmt(*CI);
+ });
}
void ASTDumper::VisitStmt(const Stmt *Node) {
@@ -1538,22 +1605,16 @@ void ASTDumper::VisitDeclStmt(const DeclStmt *Node) {
VisitStmt(Node);
for (DeclStmt::const_decl_iterator I = Node->decl_begin(),
E = Node->decl_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
+ I != E; ++I)
dumpDecl(*I);
- }
}
void ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) {
VisitStmt(Node);
for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(),
E = Node->getAttrs().end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
+ I != E; ++I)
dumpAttr(*I);
- }
}
void ASTDumper::VisitLabelStmt(const LabelStmt *Node) {
@@ -1693,15 +1754,7 @@ void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
VisitExpr(Node);
- switch (Node->getIdentType()) {
- default: llvm_unreachable("unknown case");
- case PredefinedExpr::Func: OS << " __func__"; break;
- case PredefinedExpr::Function: OS << " __FUNCTION__"; break;
- case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break;
- case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break;
- case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
- case PredefinedExpr::FuncSig: OS << " __FUNCSIG__"; break;
- }
+ OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType());
}
void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
@@ -1734,12 +1787,10 @@ void ASTDumper::VisitStringLiteral(const StringLiteral *Str) {
void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) {
VisitExpr(ILE);
if (auto *Filler = ILE->getArrayFiller()) {
- if (!ILE->getNumInits())
- lastChild();
- IndentScope Indent(*this);
- OS << "array filler";
- lastChild();
- dumpStmt(Filler);
+ dumpChild([=] {
+ OS << "array filler";
+ dumpStmt(Filler);
+ });
}
if (auto *Field = ILE->getInitializedFieldInUnion()) {
OS << " field ";
@@ -1805,10 +1856,8 @@ void ASTDumper::VisitBlockExpr(const BlockExpr *Node) {
void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
VisitExpr(Node);
- if (Expr *Source = Node->getSourceExpr()) {
- lastChild();
+ if (Expr *Source = Node->getSourceExpr())
dumpStmt(Source);
- }
}
// GNU extensions.
@@ -2024,27 +2073,24 @@ void ASTDumper::dumpFullComment(const FullComment *C) {
}
void ASTDumper::dumpComment(const Comment *C) {
- IndentScope Indent(*this);
-
- if (!C) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>>";
- return;
- }
+ dumpChild([=] {
+ if (!C) {
+ ColorScope Color(*this, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
- {
- ColorScope Color(*this, CommentColor);
- OS << C->getCommentKindName();
- }
- dumpPointer(C);
- dumpSourceRange(C->getSourceRange());
- ConstCommentVisitor<ASTDumper>::visit(C);
- for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
- I != E; ++I) {
- if (I + 1 == E)
- lastChild();
- dumpComment(*I);
- }
+ {
+ ColorScope Color(*this, CommentColor);
+ OS << C->getCommentKindName();
+ }
+ dumpPointer(C);
+ dumpSourceRange(C->getSourceRange());
+ ConstCommentVisitor<ASTDumper>::visit(C);
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I)
+ dumpComment(*I);
+ });
}
void ASTDumper::visitTextComment(const TextComment *C) {
@@ -2148,6 +2194,23 @@ void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) {
}
//===----------------------------------------------------------------------===//
+// Type method implementations
+//===----------------------------------------------------------------------===//
+
+void QualType::dump(const char *msg) const {
+ if (msg)
+ llvm::errs() << msg << ": ";
+ dump();
+}
+
+LLVM_DUMP_METHOD void QualType::dump() const {
+ ASTDumper Dumper(llvm::errs(), nullptr, nullptr);
+ Dumper.dumpTypeAsChild(*this);
+}
+
+LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
+
+//===----------------------------------------------------------------------===//
// Decl method implementations
//===----------------------------------------------------------------------===//
@@ -2169,13 +2232,14 @@ LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
dumpLookups(llvm::errs());
}
-LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS) const {
+LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
+ bool DumpDecls) const {
const DeclContext *DC = this;
while (!DC->isTranslationUnit())
DC = DC->getParent();
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager());
- P.dumpLookups(this);
+ P.dumpLookups(this, DumpDecls);
}
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
index b0e0b1d..2442e8e 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -151,6 +151,7 @@ namespace clang {
Decl *VisitObjCMethodDecl(ObjCMethodDecl *D);
Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D);
Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D);
+ Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D);
Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
@@ -1622,15 +1623,14 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn;
ToEPI.TypeQuals = FromEPI.TypeQuals;
ToEPI.RefQualifier = FromEPI.RefQualifier;
- ToEPI.NumExceptions = ExceptionTypes.size();
- ToEPI.Exceptions = ExceptionTypes.data();
- ToEPI.ConsumedParameters = FromEPI.ConsumedParameters;
- ToEPI.ExceptionSpecType = FromEPI.ExceptionSpecType;
- ToEPI.NoexceptExpr = Importer.Import(FromEPI.NoexceptExpr);
- ToEPI.ExceptionSpecDecl = cast_or_null<FunctionDecl>(
- Importer.Import(FromEPI.ExceptionSpecDecl));
- ToEPI.ExceptionSpecTemplate = cast_or_null<FunctionDecl>(
- Importer.Import(FromEPI.ExceptionSpecTemplate));
+ ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type;
+ ToEPI.ExceptionSpec.Exceptions = ExceptionTypes;
+ ToEPI.ExceptionSpec.NoexceptExpr =
+ Importer.Import(FromEPI.ExceptionSpec.NoexceptExpr);
+ ToEPI.ExceptionSpec.SourceDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(FromEPI.ExceptionSpec.SourceDecl));
+ ToEPI.ExceptionSpec.SourceTemplate = cast_or_null<FunctionDecl>(
+ Importer.Import(FromEPI.ExceptionSpec.SourceTemplate));
return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI);
}
@@ -2093,10 +2093,11 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
}
case TemplateArgument::Declaration: {
- ValueDecl *FromD = From.getAsDecl();
- if (ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(FromD)))
- return TemplateArgument(To, From.isDeclForReferenceParam());
- return TemplateArgument();
+ ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl()));
+ QualType ToType = Importer.Import(From.getParamTypeForDecl());
+ if (!To || ToType.isNull())
+ return TemplateArgument();
+ return TemplateArgument(To, ToType);
}
case TemplateArgument::NullPtr: {
@@ -2253,7 +2254,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
} else {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace))
continue;
@@ -2316,7 +2317,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
@@ -2396,7 +2397,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
if (!DC->isFunctionOrMethod() && SearchName) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(SearchName, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
@@ -2482,7 +2483,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(SearchName, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
@@ -2604,7 +2605,7 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
@@ -2656,7 +2657,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
@@ -2712,8 +2713,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// FunctionDecl that we are importing the FunctionProtoType for.
// To avoid an infinite recursion when importing, create the FunctionDecl
// with a simplified function type and update it afterwards.
- if (FromEPI.ExceptionSpecDecl || FromEPI.ExceptionSpecTemplate ||
- FromEPI.NoexceptExpr) {
+ if (FromEPI.ExceptionSpec.SourceDecl ||
+ FromEPI.ExceptionSpec.SourceTemplate ||
+ FromEPI.ExceptionSpec.NoexceptExpr) {
FunctionProtoType::ExtProtoInfo DefaultEPI;
FromTy = Importer.getFromContext().getFunctionType(
FromFPT->getReturnType(), FromFPT->getParamTypes(), DefaultEPI);
@@ -2858,7 +2860,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) {
// For anonymous fields, match up by index.
@@ -2914,7 +2916,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
// Determine whether we've already imported this field.
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (IndirectFieldDecl *FoundField
= dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
@@ -2958,9 +2960,12 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
}
IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create(
- Importer.getToContext(), DC,
- Loc, Name.getAsIdentifierInfo(), T,
- NamedChain, D->getChainingSize());
+ Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T,
+ NamedChain, D->getChainingSize());
+
+ for (const auto *Attr : D->attrs())
+ ToIndirectField->addAttr(Attr->clone(Importer.getToContext()));
+
ToIndirectField->setAccess(D->getAccess());
ToIndirectField->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToIndirectField);
@@ -2978,7 +2983,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
// Determine whether we've already imported this ivar
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->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(),
@@ -3033,7 +3038,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
continue;
@@ -3203,7 +3208,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
return nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->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())
@@ -3439,7 +3444,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
ObjCProtocolDecl *MergeWithProtocol = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
continue;
@@ -3466,6 +3471,36 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
return ToProto;
}
+Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+
+ SourceLocation ExternLoc = Importer.Import(D->getExternLoc());
+ SourceLocation LangLoc = Importer.Import(D->getLocation());
+
+ bool HasBraces = D->hasBraces();
+
+ LinkageSpecDecl *ToLinkageSpec =
+ LinkageSpecDecl::Create(Importer.getToContext(),
+ DC,
+ ExternLoc,
+ LangLoc,
+ D->getLanguage(),
+ HasBraces);
+
+ if (HasBraces) {
+ SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc());
+ ToLinkageSpec->setRBraceLoc(RBraceLoc);
+ }
+
+ ToLinkageSpec->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToLinkageSpec);
+
+ Importer.Imported(D, ToLinkageSpec);
+
+ return ToLinkageSpec;
+}
+
bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
ObjCInterfaceDecl *To,
ImportDefinitionKind Kind) {
@@ -3585,7 +3620,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
// Look for an existing interface with the same name.
ObjCInterfaceDecl *MergeWithIface = nullptr;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
@@ -3739,7 +3774,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
// Check whether we have already imported this property.
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (ObjCPropertyDecl *FoundProp
= dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) {
@@ -3972,7 +4007,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
@@ -4161,7 +4196,7 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
"Variable templates cannot be declared at function scope");
SmallVector<NamedDecl *, 4> ConflictingDecls;
SmallVector<NamedDecl *, 2> FoundDecls;
- DC->localUncachedLookup(Name, FoundDecls);
+ DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
@@ -4371,7 +4406,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
Importer.Import(E->getQualifierLoc()),
Importer.Import(E->getTemplateKeywordLoc()),
ToD,
- E->refersToEnclosingLocal(),
+ E->refersToEnclosingVariableOrCapture(),
Importer.Import(E->getLocation()),
T, E->getValueKind(),
FoundD,
@@ -4760,6 +4795,13 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
case NestedNameSpecifier::Global:
return NestedNameSpecifier::GlobalSpecifier(ToContext);
+ case NestedNameSpecifier::Super:
+ if (CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
+ return NestedNameSpecifier::SuperSpecifier(ToContext, RD);
+ }
+ return nullptr;
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
QualType T = Import(QualType(FromNNS->getAsType(), 0u));
@@ -4882,7 +4924,10 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
FromLoc = FromSM.getSpellingLoc(FromLoc);
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
SourceManager &ToSM = ToContext.getSourceManager();
- return ToSM.getLocForStartOfFile(Import(Decomposed.first))
+ FileID ToFileID = Import(Decomposed.first);
+ if (ToFileID.isInvalid())
+ return SourceLocation();
+ return ToSM.getLocForStartOfFile(ToFileID)
.getLocWithOffset(Decomposed.second);
}
@@ -4913,16 +4958,19 @@ FileID ASTImporter::Import(FileID FromID) {
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
// than mmap the files several times.
const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName());
+ if (!Entry)
+ return FileID();
ToID = ToSM.createFileID(Entry, ToIncludeLoc,
FromSLoc.getFile().getFileCharacteristic());
} else {
// FIXME: We want to re-use the existing MemoryBuffer!
const llvm::MemoryBuffer *
FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM);
- llvm::MemoryBuffer *ToBuf
+ std::unique_ptr<llvm::MemoryBuffer> ToBuf
= llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
FromBuf->getBufferIdentifier());
- ToID = ToSM.createFileID(ToBuf, FromSLoc.getFile().getFileCharacteristic());
+ ToID = ToSM.createFileID(std::move(ToBuf),
+ FromSLoc.getFile().getFileCharacteristic());
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp
index baa8e48..ec0671c 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp
@@ -62,6 +62,53 @@ bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived,
StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }
+ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1,
+ ASTNodeKind Kind2) {
+ if (Kind1.isBaseOf(Kind2)) return Kind2;
+ if (Kind2.isBaseOf(Kind1)) return Kind1;
+ return ASTNodeKind();
+}
+
+ASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1,
+ ASTNodeKind Kind2) {
+ NodeKindId Parent = Kind1.KindId;
+ while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None) {
+ Parent = AllKindInfo[Parent].ParentId;
+ }
+ return ASTNodeKind(Parent);
+}
+
+ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) {
+ switch (D.getKind()) {
+#define DECL(DERIVED, BASE) \
+ case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl);
+#define ABSTRACT_DECL(D)
+#include "clang/AST/DeclNodes.inc"
+ };
+ llvm_unreachable("invalid decl kind");
+}
+
+ASTNodeKind ASTNodeKind::getFromNode(const Stmt &S) {
+ switch (S.getStmtClass()) {
+ case Stmt::NoStmtClass: return NKI_None;
+#define STMT(CLASS, PARENT) \
+ case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS);
+#define ABSTRACT_STMT(S)
+#include "clang/AST/StmtNodes.inc"
+ }
+ llvm_unreachable("invalid stmt kind");
+}
+
+ASTNodeKind ASTNodeKind::getFromNode(const Type &T) {
+ switch (T.getTypeClass()) {
+#define TYPE(Class, Base) \
+ case Type::Class: return ASTNodeKind(NKI_##Class##Type);
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ }
+ llvm_unreachable("invalid type kind");
+}
+
void DynTypedNode::print(llvm::raw_ostream &OS,
const PrintingPolicy &PP) const {
if (const TemplateArgument *TA = get<TemplateArgument>())
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
index 12b929b..8e9e358 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h
+++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_CXXABI_H
-#define LLVM_CLANG_AST_CXXABI_H
+#ifndef LLVM_CLANG_LIB_AST_CXXABI_H
+#define LLVM_CLANG_LIB_AST_CXXABI_H
#include "clang/AST/Type.h"
diff --git a/contrib/llvm/tools/clang/lib/AST/Comment.cpp b/contrib/llvm/tools/clang/lib/AST/Comment.cpp
index 4f43346..d05c5de 100644
--- a/contrib/llvm/tools/clang/lib/AST/Comment.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Comment.cpp
@@ -157,8 +157,7 @@ void DeclInfo::fill() {
case Decl::CXXConversion: {
const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl);
Kind = FunctionKind;
- ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
- FD->getNumParams());
+ ParamVars = llvm::makeArrayRef(FD->param_begin(), FD->getNumParams());
ReturnType = FD->getReturnType();
unsigned NumLists = FD->getNumTemplateParameterLists();
if (NumLists != 0) {
@@ -178,8 +177,7 @@ void DeclInfo::fill() {
case Decl::ObjCMethod: {
const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl);
Kind = FunctionKind;
- ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
- MD->param_size());
+ ParamVars = llvm::makeArrayRef(MD->param_begin(), MD->param_size());
ReturnType = MD->getReturnType();
IsObjCMethod = true;
IsInstanceMethod = MD->isInstanceMethod();
@@ -191,8 +189,7 @@ void DeclInfo::fill() {
Kind = FunctionKind;
TemplateKind = Template;
const FunctionDecl *FD = FTD->getTemplatedDecl();
- ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
- FD->getNumParams());
+ ParamVars = llvm::makeArrayRef(FD->param_begin(), FD->getNumParams());
ReturnType = FD->getReturnType();
TemplateParameters = FTD->getTemplateParameters();
break;
@@ -278,9 +275,7 @@ void DeclInfo::fill() {
// Is this a typedef for a function type?
if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
Kind = FunctionKind;
- ArrayRef<ParmVarDecl *> Params = FTL.getParams();
- ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(),
- Params.size());
+ ParamVars = FTL.getParams();
ReturnType = FTL.getReturnLoc().getType();
break;
}
@@ -299,9 +294,7 @@ void DeclInfo::fill() {
TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc();
if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
Kind = FunctionKind;
- ArrayRef<ParmVarDecl *> Params = FTL.getParams();
- ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(),
- Params.size());
+ ParamVars = FTL.getParams();
ReturnType = FTL.getReturnLoc().getType();
}
break;
diff --git a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp
index a7b07a4..7378a7c 100644
--- a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp
@@ -89,6 +89,10 @@ CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) {
// Value-initialize (=zero-initialize in this case) a new CommandInfo.
CommandInfo *Info = new (Allocator) CommandInfo();
Info->Name = Name;
+ // We only have a limited number of bits to encode command IDs in the
+ // CommandInfo structure, so the ID numbers can potentially wrap around.
+ assert((NextID < (1 << CommandInfo::NumCommandIDBits))
+ && "Too many commands. We have limited bits for the command ID.");
Info->ID = NextID++;
RegisteredCommands.push_back(Info);
diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
index 792a832..06a08bd 100644
--- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp
@@ -362,7 +362,7 @@ void Lexer::lexCommentText(Token &T) {
}
}
- const StringRef CommandName(BufferPtr + 1, Length);
+ StringRef CommandName(BufferPtr + 1, Length);
const CommandInfo *Info = Traits.getCommandInfoOrNULL(CommandName);
if (!Info) {
@@ -531,7 +531,7 @@ void Lexer::lexVerbatimLineText(Token &T) {
// Extract current line.
const char *Newline = findNewline(BufferPtr, CommentEnd);
- const StringRef Text(BufferPtr, Newline - BufferPtr);
+ StringRef Text(BufferPtr, Newline - BufferPtr);
formTokenWithChars(T, Newline, tok::verbatim_line_text);
T.setVerbatimLineText(Text);
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
index 7448de2..e43c28a 100644
--- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -29,6 +29,7 @@
#include "clang/Basic/Module.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -38,6 +39,11 @@ Decl *clang::getPrimaryMergedDecl(Decl *D) {
return D->getASTContext().getPrimaryMergedDecl(D);
}
+// Defined here so that it can be inlined into its direct callers.
+bool Decl::isOutOfLine() const {
+ return !getLexicalDeclContext()->Equals(getDeclContext());
+}
+
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
@@ -613,9 +619,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// Explicitly declared static.
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
return LinkageInfo(InternalLinkage, DefaultVisibility, false);
+ } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
+ // - a data member of an anonymous union.
+ const VarDecl *VD = IFD->getVarDecl();
+ assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
+ return getLVForNamespaceScopeDecl(VD, computation);
}
- // - a data member of an anonymous union.
- assert(!isa<IndirectFieldDecl>(D) && "Didn't expect an IndirectFieldDecl!");
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
if (D->isInAnonymousNamespace()) {
@@ -811,6 +820,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// Everything not covered here has no linkage.
} else {
+ // FIXME: A typedef declaration has linkage if it gives a type a name for
+ // linkage purposes.
return LinkageInfo::none();
}
@@ -994,6 +1005,19 @@ bool NamedDecl::isLinkageValid() const {
getCachedLinkage();
}
+ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
+ StringRef name = getName();
+ if (name.empty()) return SFF_None;
+
+ if (name.front() == 'C')
+ if (name == "CFStringCreateWithFormat" ||
+ name == "CFStringCreateWithFormatAndArguments" ||
+ name == "CFStringAppendFormat" ||
+ name == "CFStringAppendFormatAndArguments")
+ return SFF_CFString;
+ return SFF_None;
+}
+
Linkage NamedDecl::getLinkageInternal() const {
// We don't care about visibility here, so ask for the cheapest
// possible visibility analysis.
@@ -1168,7 +1192,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
} else {
const FunctionDecl *FD = cast<FunctionDecl>(OuterD);
if (!FD->isInlined() &&
- FD->getTemplateSpecializationKind() == TSK_Undeclared)
+ !isTemplateInstantiation(FD->getTemplateSpecializationKind()))
return LinkageInfo::none();
LV = getLVForDecl(FD, computation);
@@ -2607,7 +2631,7 @@ void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) {
if (!NewDecls.empty()) {
NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()];
std::copy(NewDecls.begin(), NewDecls.end(), A);
- DeclsInPrototypeScope = ArrayRef<NamedDecl *>(A, NewDecls.size());
+ DeclsInPrototypeScope = llvm::makeArrayRef(A, NewDecls.size());
// Move declarations introduced in prototype to the function context.
for (auto I : NewDecls) {
DeclContext *DC = I->getDeclContext();
@@ -3168,8 +3192,11 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
return Builtin::BImemmove;
case Builtin::BIstrlcpy:
+ case Builtin::BI__builtin___strlcpy_chk:
return Builtin::BIstrlcpy;
+
case Builtin::BIstrlcat:
+ case Builtin::BI__builtin___strlcat_chk:
return Builtin::BIstrlcat;
case Builtin::BI__builtin_memcmp:
@@ -3261,7 +3288,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
assert(isBitField() && "not a bitfield");
- Expr *BitWidth = InitializerOrBitWidth.getPointer();
+ Expr *BitWidth = static_cast<Expr *>(InitStorage.getPointer());
return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue();
}
@@ -3275,30 +3302,39 @@ unsigned FieldDecl::getFieldIndex() const {
unsigned Index = 0;
const RecordDecl *RD = getParent();
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I, ++Index)
- I->getCanonicalDecl()->CachedFieldIndex = Index + 1;
+ for (auto *Field : RD->fields()) {
+ Field->getCanonicalDecl()->CachedFieldIndex = Index + 1;
+ ++Index;
+ }
assert(CachedFieldIndex && "failed to find field in parent");
return CachedFieldIndex - 1;
}
SourceRange FieldDecl::getSourceRange() const {
- if (const Expr *E = InitializerOrBitWidth.getPointer())
- return SourceRange(getInnerLocStart(), E->getLocEnd());
- return DeclaratorDecl::getSourceRange();
-}
+ switch (InitStorage.getInt()) {
+ // All three of these cases store an optional Expr*.
+ case ISK_BitWidthOrNothing:
+ case ISK_InClassCopyInit:
+ case ISK_InClassListInit:
+ if (const Expr *E = static_cast<const Expr *>(InitStorage.getPointer()))
+ return SourceRange(getInnerLocStart(), E->getLocEnd());
+ // FALLTHROUGH
-void FieldDecl::setBitWidth(Expr *Width) {
- assert(!InitializerOrBitWidth.getPointer() && !hasInClassInitializer() &&
- "bit width or initializer already set");
- InitializerOrBitWidth.setPointer(Width);
+ case ISK_CapturedVLAType:
+ return DeclaratorDecl::getSourceRange();
+ }
+ llvm_unreachable("bad init storage kind");
}
-void FieldDecl::setInClassInitializer(Expr *Init) {
- assert(!InitializerOrBitWidth.getPointer() && hasInClassInitializer() &&
- "bit width or initializer already set");
- InitializerOrBitWidth.setPointer(Init);
+void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
+ assert((getParent()->isLambda() || getParent()->isCapturedRecord()) &&
+ "capturing type in non-lambda or captured record.");
+ assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
+ InitStorage.getPointer() == nullptr &&
+ "bit width, initializer or captured type already set");
+ InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType),
+ ISK_CapturedVLAType);
}
//===----------------------------------------------------------------------===//
@@ -3521,6 +3557,20 @@ bool RecordDecl::isInjectedClassName() const {
cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
}
+bool RecordDecl::isLambda() const {
+ if (auto RD = dyn_cast<CXXRecordDecl>(this))
+ return RD->isLambda();
+ return false;
+}
+
+bool RecordDecl::isCapturedRecord() const {
+ return hasAttr<CapturedRecordAttr>();
+}
+
+void RecordDecl::setCapturedRecord() {
+ addAttr(CapturedRecordAttr::CreateImplicit(getASTContext()));
+}
+
RecordDecl::field_iterator RecordDecl::field_begin() const {
if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage)
LoadFieldsFromExternalStorage();
@@ -3578,6 +3628,64 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
/*FieldsAlreadyLoaded=*/false);
}
+bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
+ ASTContext &Context = getASTContext();
+ if (!Context.getLangOpts().Sanitize.has(SanitizerKind::Address) ||
+ !Context.getLangOpts().SanitizeAddressFieldPadding)
+ return false;
+ const auto &Blacklist = Context.getSanitizerBlacklist();
+ const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this);
+ // We may be able to relax some of these requirements.
+ int ReasonToReject = -1;
+ if (!CXXRD || CXXRD->isExternCContext())
+ ReasonToReject = 0; // is not C++.
+ else if (CXXRD->hasAttr<PackedAttr>())
+ ReasonToReject = 1; // is packed.
+ else if (CXXRD->isUnion())
+ ReasonToReject = 2; // is a union.
+ else if (CXXRD->isTriviallyCopyable())
+ ReasonToReject = 3; // is trivially copyable.
+ else if (CXXRD->hasTrivialDestructor())
+ ReasonToReject = 4; // has trivial destructor.
+ else if (CXXRD->isStandardLayout())
+ ReasonToReject = 5; // is standard layout.
+ else if (Blacklist.isBlacklistedLocation(getLocation(), "field-padding"))
+ ReasonToReject = 6; // is in a blacklisted file.
+ else if (Blacklist.isBlacklistedType(getQualifiedNameAsString(),
+ "field-padding"))
+ ReasonToReject = 7; // is blacklisted.
+
+ if (EmitRemark) {
+ if (ReasonToReject >= 0)
+ Context.getDiagnostics().Report(
+ getLocation(),
+ diag::remark_sanitize_address_insert_extra_padding_rejected)
+ << getQualifiedNameAsString() << ReasonToReject;
+ else
+ Context.getDiagnostics().Report(
+ getLocation(),
+ diag::remark_sanitize_address_insert_extra_padding_accepted)
+ << getQualifiedNameAsString();
+ }
+ return ReasonToReject < 0;
+}
+
+const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
+ for (const auto *I : fields()) {
+ if (I->getIdentifier())
+ return I;
+
+ if (const RecordType *RT = I->getType()->getAs<RecordType>())
+ if (const FieldDecl *NamedDataMember =
+ RT->getDecl()->findFirstNamedDataMember())
+ return NamedDataMember;
+ }
+
+ // We didn't find a named data member.
+ return nullptr;
+}
+
+
//===----------------------------------------------------------------------===//
// BlockDecl Implementation
//===----------------------------------------------------------------------===//
@@ -3657,6 +3765,13 @@ LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
SourceLocation());
}
+void LabelDecl::setMSAsmLabel(StringRef Name) {
+ char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
+ memcpy(Buffer, Name.data(), Name.size());
+ Buffer[Name.size()] = '\0';
+ MSAsmName = Buffer;
+}
+
void ValueDecl::anchor() { }
bool ValueDecl::isWeak() const {
@@ -3892,8 +4007,8 @@ ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
const SourceLocation *StoredLocs
= reinterpret_cast<const SourceLocation *>(this + 1);
- return ArrayRef<SourceLocation>(StoredLocs,
- getNumModuleIdentifiers(getImportedModule()));
+ return llvm::makeArrayRef(StoredLocs,
+ getNumModuleIdentifiers(getImportedModule()));
}
SourceRange ImportDecl::getSourceRange() const {
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
index 2b1506d..a46787f 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -374,8 +374,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
+ VersionTuple VTI(A->getIntroduced());
+ VTI.UseDotAsSeparator();
Out << "introduced in " << PrettyPlatformName << ' '
- << A->getIntroduced() << HintMessage;
+ << VTI << HintMessage;
}
return AR_NotYetIntroduced;
@@ -386,8 +388,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
+ VersionTuple VTO(A->getObsoleted());
+ VTO.UseDotAsSeparator();
Out << "obsoleted in " << PrettyPlatformName << ' '
- << A->getObsoleted() << HintMessage;
+ << VTO << HintMessage;
}
return AR_Unavailable;
@@ -398,8 +402,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
+ VersionTuple VTD(A->getDeprecated());
+ VTD.UseDotAsSeparator();
Out << "first deprecated in " << PrettyPlatformName << ' '
- << A->getDeprecated() << HintMessage;
+ << VTD << HintMessage;
}
return AR_Deprecated;
@@ -1296,6 +1302,11 @@ DeclContext::lookup(DeclarationName Name) {
if (PrimaryContext != this)
return PrimaryContext->lookup(Name);
+ // If this is a namespace, ensure that any later redeclarations of it have
+ // been loaded, since they may add names to the result of this lookup.
+ if (auto *ND = dyn_cast<NamespaceDecl>(this))
+ (void)ND->getMostRecentDecl();
+
if (hasExternalVisibleStorage()) {
if (NeedToReconcileExternalVisibleStorage)
reconcileExternalVisibleStorage();
@@ -1430,6 +1441,17 @@ DeclContext *DeclContext::getEnclosingNamespaceContext() {
return Ctx->getPrimaryContext();
}
+RecordDecl *DeclContext::getOuterLexicalRecordContext() {
+ // Loop until we find a non-record context.
+ RecordDecl *OutermostRD = nullptr;
+ DeclContext *DC = this;
+ while (DC->isRecord()) {
+ OutermostRD = cast<RecordDecl>(DC);
+ DC = DC->getLexicalParent();
+ }
+ return OutermostRD;
+}
+
bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
// For non-file contexts, this is equivalent to Equals.
if (!isFileContext())
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
index ed26c52..a6d9d41 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -209,7 +209,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// Now go through all virtual bases of this base and add them.
for (const auto &VBase : BaseClassDecl->vbases()) {
// Add this base if it's not already in the list.
- if (SeenVBaseTypes.insert(C.getCanonicalType(VBase.getType()))) {
+ if (SeenVBaseTypes.insert(C.getCanonicalType(VBase.getType())).second) {
VBases.push_back(&VBase);
// C++11 [class.copy]p8:
@@ -225,7 +225,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (Base->isVirtual()) {
// Add this base if it's not already in the list.
- if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)))
+ if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)).second)
VBases.push_back(Base);
// C++0x [meta.unary.prop] is_empty:
@@ -677,17 +677,24 @@ void CXXRecordDecl::addedMember(Decl *D) {
//
// Automatic Reference Counting: the presence of a member of Objective-C pointer type
// that does not explicitly have no lifetime makes the class a non-POD.
- // However, we delay setting PlainOldData to false in this case so that
- // Sema has a chance to diagnostic causes where the same class will be
- // non-POD with Automatic Reference Counting but a POD without ARC.
- // In this case, the class will become a non-POD class when we complete
- // the definition.
ASTContext &Context = getASTContext();
QualType T = Context.getBaseElementType(Field->getType());
if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
- if (!Context.getLangOpts().ObjCAutoRefCount ||
- T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone)
+ if (!Context.getLangOpts().ObjCAutoRefCount) {
setHasObjectMember(true);
+ } else if (T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
+ // Objective-C Automatic Reference Counting:
+ // If a class has a non-static data member of Objective-C pointer
+ // type (or array thereof), it is a non-POD type and its
+ // default constructor (if any), copy constructor, move constructor,
+ // copy assignment operator, move assignment operator, and destructor are
+ // non-trivial.
+ setHasObjectMember(true);
+ struct DefinitionData &Data = data();
+ Data.PlainOldData = false;
+ Data.HasTrivialSpecialMembers = 0;
+ Data.HasIrrelevantDestructor = false;
+ }
} else if (!T.isCXX98PODType(Context))
data().PlainOldData = false;
@@ -720,7 +727,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// brace-or-equal-initializers for non-static data members.
//
// This rule was removed in C++1y.
- if (!getASTContext().getLangOpts().CPlusPlus1y)
+ if (!getASTContext().getLangOpts().CPlusPlus14)
data().Aggregate = false;
// C++11 [class]p10:
@@ -1254,6 +1261,44 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
llvm_unreachable("Not a class template or member class specialization");
}
+const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
+ // If it's a class template specialization, find the template or partial
+ // specialization from which it was instantiated.
+ if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
+ auto From = TD->getInstantiatedFrom();
+ if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
+ while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
+ if (NewCTD->isMemberSpecialization())
+ break;
+ CTD = NewCTD;
+ }
+ return CTD->getTemplatedDecl();
+ }
+ if (auto *CTPSD =
+ From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
+ while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
+ if (NewCTPSD->isMemberSpecialization())
+ break;
+ CTPSD = NewCTPSD;
+ }
+ return CTPSD;
+ }
+ }
+
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
+ if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
+ const CXXRecordDecl *RD = this;
+ while (auto *NewRD = RD->getInstantiatedFromMemberClass())
+ RD = NewRD;
+ return RD;
+ }
+ }
+
+ assert(!isTemplateInstantiation(this->getTemplateSpecializationKind()) &&
+ "couldn't find pattern for class template instantiation");
+ return nullptr;
+}
+
CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
ASTContext &Context = getASTContext();
QualType ClassType = Context.getTypeDeclType(this);
@@ -1277,19 +1322,6 @@ void CXXRecordDecl::completeDefinition() {
void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
RecordDecl::completeDefinition();
- if (hasObjectMember() && getASTContext().getLangOpts().ObjCAutoRefCount) {
- // Objective-C Automatic Reference Counting:
- // If a class has a non-static data member of Objective-C pointer
- // type (or array thereof), it is a non-POD type and its
- // default constructor (if any), copy constructor, move constructor,
- // copy assignment operator, move assignment operator, and destructor are
- // non-trivial.
- struct DefinitionData &Data = data();
- Data.PlainOldData = false;
- Data.HasTrivialSpecialMembers = 0;
- Data.HasIrrelevantDestructor = false;
- }
-
// If the class may be abstract (but hasn't been marked as such), check for
// any pure final overriders.
if (mayBeAbstract()) {
@@ -1799,7 +1831,6 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const {
bool CXXConstructorDecl::isSpecializationCopyingObject() const {
if ((getNumParams() < 1) ||
(getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
- (getPrimaryTemplate() == nullptr) ||
(getDescribedFunctionTemplate() != nullptr))
return false;
@@ -1970,6 +2001,16 @@ NamespaceDecl *NamespaceDecl::getMostRecentDeclImpl() {
void NamespaceAliasDecl::anchor() { }
+NamespaceAliasDecl *NamespaceAliasDecl::getNextRedeclarationImpl() {
+ return getNextRedeclaration();
+}
+NamespaceAliasDecl *NamespaceAliasDecl::getPreviousDeclImpl() {
+ return getPreviousDecl();
+}
+NamespaceAliasDecl *NamespaceAliasDecl::getMostRecentDeclImpl() {
+ return getMostRecentDecl();
+}
+
NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceLocation AliasLoc,
@@ -1977,15 +2018,16 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Namespace) {
+ // FIXME: Preserve the aliased namespace as written.
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
- return new (C, DC) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias,
+ return new (C, DC) NamespaceAliasDecl(C, DC, UsingLoc, AliasLoc, Alias,
QualifierLoc, IdentLoc, Namespace);
}
NamespaceAliasDecl *
NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) NamespaceAliasDecl(nullptr, SourceLocation(),
+ return new (C, ID) NamespaceAliasDecl(C, nullptr, SourceLocation(),
SourceLocation(), nullptr,
NestedNameSpecifierLoc(),
SourceLocation(), nullptr);
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
index 2204dff..ed53675 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
@@ -93,13 +93,13 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
return nullptr;
}
-/// HasUserDeclaredSetterMethod - This routine returns 'true' if a user declared setter
-/// method was found in the class, its protocols, its super classes or categories.
-/// It also returns 'true' if one of its categories has declared a 'readwrite' property.
-/// This is because, user must provide a setter method for the category's 'readwrite'
-/// property.
-bool
-ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) const {
+/// \brief This routine returns 'true' if a user declared setter method was
+/// found in the class, its protocols, its super classes or categories.
+/// It also returns 'true' if one of its categories has declared a 'readwrite'
+/// property. This is because, user must provide a setter method for the
+/// category's 'readwrite' property.
+bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
+ const ObjCPropertyDecl *Property) const {
Selector Sel = Property->getSetterName();
lookup_const_result R = lookup(Sel);
for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end();
@@ -118,9 +118,10 @@ ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property)
return true;
if (Cat->IsClassExtension())
continue;
- // Also search through the categories looking for a 'readwrite' declaration
- // of this property. If one found, presumably a setter will be provided
- // (properties declared in categories will not get auto-synthesized).
+ // Also search through the categories looking for a 'readwrite'
+ // declaration of this property. If one found, presumably a setter will
+ // be provided (properties declared in categories will not get
+ // auto-synthesized).
for (const auto *P : Cat->properties())
if (P->getIdentifier() == Property->getIdentifier()) {
if (P->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite)
@@ -151,7 +152,7 @@ ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property)
ObjCPropertyDecl *
ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
- IdentifierInfo *propertyID) {
+ const IdentifierInfo *propertyID) {
// If this context is a hidden protocol definition, don't find any
// property.
if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
@@ -181,8 +182,8 @@ ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const {
/// FindPropertyDeclaration - Finds declaration of the property given its name
/// in 'PropertyId' and returns it. It returns 0, if not found.
-ObjCPropertyDecl *
-ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
+ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
+ const IdentifierInfo *PropertyId) const {
// Don't find properties within hidden protocol definitions.
if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
if (const ObjCProtocolDecl *Def = Proto->getDefinition())
@@ -558,36 +559,39 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
LoadExternalDefinition();
while (ClassDecl) {
+ // 1. Look through primary class.
if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
return MethodDecl;
-
- // Didn't find one yet - look through protocols.
- for (const auto *I : ClassDecl->protocols())
- if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
- return MethodDecl;
- // Didn't find one yet - now look through categories.
- for (const auto *Cat : ClassDecl->visible_categories()) {
+ // 2. Didn't find one yet - now look through categories.
+ for (const auto *Cat : ClassDecl->visible_categories())
if ((MethodDecl = Cat->getMethod(Sel, isInstance)))
if (C != Cat || !MethodDecl->isImplicit())
return MethodDecl;
- if (!shallowCategoryLookup) {
+ // 3. Didn't find one yet - look through primary class's protocols.
+ for (const auto *I : ClassDecl->protocols())
+ if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
+ return MethodDecl;
+
+ // 4. Didn't find one yet - now look through categories' protocols
+ if (!shallowCategoryLookup)
+ for (const auto *Cat : ClassDecl->visible_categories()) {
// Didn't find one yet - look through protocols.
const ObjCList<ObjCProtocolDecl> &Protocols =
- Cat->getReferencedProtocols();
+ Cat->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end(); I != E; ++I)
if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
if (C != Cat || !MethodDecl->isImplicit())
return MethodDecl;
}
- }
-
+
+
if (!followSuper)
return nullptr;
- // Get the super class (if any).
+ // 5. Get to the super class (if any).
ClassDecl = ClassDecl->getSuperClass();
}
return nullptr;
@@ -849,6 +853,11 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
family = OMF_None;
break;
+ case OMF_initialize:
+ if (isInstanceMethod() || !getReturnType()->isVoidType())
+ family = OMF_None;
+ break;
+
case OMF_performSelector:
if (!isInstanceMethod() || !getReturnType()->isObjCIdType())
family = OMF_None;
@@ -952,6 +961,13 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
llvm_unreachable("unknown method context");
}
+SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const {
+ const auto *TSI = getReturnTypeSourceInfo();
+ if (TSI)
+ return TSI->getTypeLoc().getSourceRange();
+ return SourceRange();
+}
+
static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
const ObjCMethodDecl *Method,
SmallVectorImpl<const ObjCMethodDecl *> &Methods,
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
index e5e5130..c0f3e17 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -87,6 +87,7 @@ namespace {
void PrintTemplateParameters(const TemplateParameterList *Params,
const TemplateArgumentList *Args = nullptr);
void prettyPrintAttributes(Decl *D);
+ void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
};
}
@@ -197,6 +198,17 @@ void DeclPrinter::prettyPrintAttributes(Decl *D) {
}
}
+void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
+ // Normally, a PackExpansionType is written as T[3]... (for instance, as a
+ // template argument), but if it is the type of a declaration, the ellipsis
+ // is placed before the name being declared.
+ if (auto *PET = T->getAs<PackExpansionType>()) {
+ Pack = true;
+ T = PET->getPattern();
+ }
+ T.print(Out, Policy, (Pack ? "..." : "") + DeclName);
+}
+
void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
this->Indent();
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
@@ -365,6 +377,9 @@ void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
Out << "__module_private__ ";
Out << D->getKindName();
+
+ prettyPrintAttributes(D);
+
if (D->getIdentifier())
Out << ' ' << *D;
@@ -647,7 +662,6 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
Out << *D << ":";
}
-
void DeclPrinter::VisitVarDecl(VarDecl *D) {
if (!Policy.SuppressSpecifiers) {
StorageClass SC = D->getStorageClass();
@@ -675,7 +689,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
QualType T = D->getTypeSourceInfo()
? D->getTypeSourceInfo()->getType()
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
- T.print(Out, Policy, D->getName());
+ printDeclType(T, D->getName());
Expr *Init = D->getInit();
if (!Policy.SuppressInitializers && Init) {
bool ImplicitInit = false;
@@ -757,6 +771,9 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
Out << "__module_private__ ";
Out << D->getKindName();
+
+ prettyPrintAttributes(D);
+
if (D->getIdentifier())
Out << ' ' << *D;
@@ -773,9 +790,11 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
Out << "virtual ";
AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
- if (AS != AS_none)
+ if (AS != AS_none) {
Print(AS);
- Out << " " << Base->getType().getAsString(Policy);
+ Out << " ";
+ }
+ Out << Base->getType().getAsString(Policy);
if (Base->isPackExpansion())
Out << "...";
@@ -830,7 +849,7 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
Out << "class ";
if (TTP->isParameterPack())
- Out << "... ";
+ Out << "...";
Out << *TTP;
@@ -843,15 +862,10 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
};
} else if (const NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- Out << NTTP->getType().getAsString(Policy);
-
- if (NTTP->isParameterPack() && !isa<PackExpansionType>(NTTP->getType()))
- Out << "...";
-
- if (IdentifierInfo *Name = NTTP->getIdentifier()) {
- Out << ' ';
- Out << Name->getName();
- }
+ StringRef Name;
+ if (IdentifierInfo *II = NTTP->getIdentifier())
+ Name = II->getName();
+ printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
if (Args) {
Out << " = ";
@@ -940,11 +954,12 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isVariadic())
Out << ", ...";
+
+ prettyPrintAttributes(OMD);
if (OMD->getBody() && !Policy.TerseOutput) {
Out << ' ';
OMD->getBody()->printPretty(Out, nullptr, Policy);
- Out << '\n';
}
else if (Policy.PolishForDeclaration)
Out << ';';
@@ -954,6 +969,7 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
std::string I = OID->getNameAsString();
ObjCInterfaceDecl *SID = OID->getSuperClass();
+ bool eolnOut = false;
if (SID)
Out << "@implementation " << I << " : " << *SID;
else
@@ -961,6 +977,7 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
if (OID->ivar_size() > 0) {
Out << "{\n";
+ eolnOut = true;
Indentation += Policy.Indentation;
for (const auto *I : OID->ivars()) {
Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
@@ -969,7 +986,13 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
Indentation -= Policy.Indentation;
Out << "}\n";
}
+ else if (SID || (OID->decls_begin() != OID->decls_end())) {
+ Out << "\n";
+ eolnOut = true;
+ }
VisitDeclContext(OID, false);
+ if (!eolnOut)
+ Out << "\n";
Out << "@end";
}
@@ -1008,14 +1031,14 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
Indentation -= Policy.Indentation;
Out << "}\n";
}
- else if (SID) {
+ else if (SID || (OID->decls_begin() != OID->decls_end())) {
Out << "\n";
eolnOut = true;
}
VisitDeclContext(OID, false);
if (!eolnOut)
- Out << ' ';
+ Out << "\n";
Out << "@end";
// FIXME: implement the rest...
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index 5f559b7..712de50 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -195,12 +195,12 @@ SourceLocation Expr::getExprLoc() const {
case Stmt::NoStmtClass: llvm_unreachable("statement without class");
#define ABSTRACT_STMT(type)
#define STMT(type, base) \
- case Stmt::type##Class: llvm_unreachable(#type " is not an Expr"); break;
+ case Stmt::type##Class: break;
#define EXPR(type, base) \
case Stmt::type##Class: return getExprLocImpl<type>(this, &type::getExprLoc);
#include "clang/AST/StmtNodes.inc"
}
- llvm_unreachable("unknown statement kind");
+ llvm_unreachable("unknown expression kind");
}
//===----------------------------------------------------------------------===//
@@ -221,11 +221,11 @@ static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D,
// (TD) C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
//
- // and
+ // and
//
// (VD) C++ [temp.dep.constexpr]p2:
// An identifier is value-dependent if it is:
-
+
// (TD) - an identifier that was declared with dependent type
// (VD) - a name declared with a dependent type,
if (T->isDependentType()) {
@@ -309,29 +309,11 @@ void DeclRefExpr::computeDependence(const ASTContext &Ctx) {
bool InstantiationDependent = false;
computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent,
ValueDependent, InstantiationDependent);
-
- // (TD) C++ [temp.dep.expr]p3:
- // An id-expression is type-dependent if it contains:
- //
- // and
- //
- // (VD) C++ [temp.dep.constexpr]p2:
- // An identifier is value-dependent if it is:
- if (!TypeDependent && !ValueDependent &&
- hasExplicitTemplateArgs() &&
- TemplateSpecializationType::anyDependentTemplateArguments(
- getTemplateArgs(),
- getNumTemplateArgs(),
- InstantiationDependent)) {
- TypeDependent = true;
- ValueDependent = true;
- InstantiationDependent = true;
- }
-
- ExprBits.TypeDependent = TypeDependent;
- ExprBits.ValueDependent = ValueDependent;
- ExprBits.InstantiationDependent = InstantiationDependent;
-
+
+ ExprBits.TypeDependent |= TypeDependent;
+ ExprBits.ValueDependent |= ValueDependent;
+ ExprBits.InstantiationDependent |= InstantiationDependent;
+
// Is the declaration a parameter pack?
if (getDecl()->isParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -340,7 +322,7 @@ void DeclRefExpr::computeDependence(const ASTContext &Ctx) {
DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
- ValueDecl *D, bool RefersToEnclosingLocal,
+ ValueDecl *D, bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
@@ -348,14 +330,21 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
: Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) {
DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0;
- if (QualifierLoc)
+ if (QualifierLoc) {
getInternalQualifierLoc() = QualifierLoc;
+ auto *NNS = QualifierLoc.getNestedNameSpecifier();
+ if (NNS->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (NNS->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+ }
DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0;
if (FoundD)
getInternalFoundDecl() = FoundD;
DeclRefExprBits.HasTemplateKWAndArgsInfo
= (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0;
- DeclRefExprBits.RefersToEnclosingLocal = RefersToEnclosingLocal;
+ DeclRefExprBits.RefersToEnclosingVariableOrCapture =
+ RefersToEnclosingVariableOrCapture;
if (TemplateArgs) {
bool Dependent = false;
bool InstantiationDependent = false;
@@ -364,8 +353,9 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
Dependent,
InstantiationDependent,
ContainsUnexpandedParameterPack);
- if (InstantiationDependent)
- setInstantiationDependent(true);
+ assert(!Dependent && "built a DeclRefExpr with dependent template args");
+ ExprBits.InstantiationDependent |= InstantiationDependent;
+ ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
} else if (TemplateKWLoc.isValid()) {
getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
@@ -378,14 +368,14 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D,
- bool RefersToEnclosingLocal,
+ bool RefersToEnclosingVariableOrCapture,
SourceLocation NameLoc,
QualType T,
ExprValueKind VK,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs) {
return Create(Context, QualifierLoc, TemplateKWLoc, D,
- RefersToEnclosingLocal,
+ RefersToEnclosingVariableOrCapture,
DeclarationNameInfo(D->getDeclName(), NameLoc),
T, VK, FoundD, TemplateArgs);
}
@@ -394,7 +384,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D,
- bool RefersToEnclosingLocal,
+ bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo,
QualType T,
ExprValueKind VK,
@@ -416,7 +406,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
- RefersToEnclosingLocal,
+ RefersToEnclosingVariableOrCapture,
NameInfo, FoundD, TemplateArgs, T, VK);
}
@@ -448,6 +438,38 @@ SourceLocation DeclRefExpr::getLocEnd() const {
return getNameInfo().getLocEnd();
}
+PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
+ StringLiteral *SL)
+ : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary,
+ FNTy->isDependentType(), FNTy->isDependentType(),
+ FNTy->isInstantiationDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(L), Type(IT), FnName(SL) {}
+
+StringLiteral *PredefinedExpr::getFunctionName() {
+ return cast_or_null<StringLiteral>(FnName);
+}
+
+StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) {
+ switch (IT) {
+ case Func:
+ return "__func__";
+ case Function:
+ return "__FUNCTION__";
+ case FuncDName:
+ return "__FUNCDNAME__";
+ case LFunction:
+ return "L__FUNCTION__";
+ case PrettyFunction:
+ return "__PRETTY_FUNCTION__";
+ case FuncSig:
+ return "__FUNCSIG__";
+ case PrettyFunctionNoVirtual:
+ break;
+ }
+ llvm_unreachable("Unknown ident type for PredefinedExpr");
+}
+
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
// expr" policy instead.
std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
@@ -477,6 +499,22 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
}
return "";
}
+ if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) {
+ std::unique_ptr<MangleContext> MC;
+ MC.reset(Context.createMangleContext());
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ auto DC = CurrentDecl->getDeclContext();
+ if (DC->isFileContext())
+ MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out);
+ else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
+ MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
+ else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
+ MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
+ else
+ MC->mangleBlock(DC, BD, Out);
+ return Out.str();
+ }
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
return FD->getNameAsString();
@@ -509,6 +547,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
case CC_X86StdCall: POut << "__stdcall "; break;
case CC_X86FastCall: POut << "__fastcall "; break;
case CC_X86ThisCall: POut << "__thiscall "; break;
+ case CC_X86VectorCall: POut << "__vectorcall "; break;
// Only bother printing the conventions that MSVC knows about.
default: break;
}
@@ -600,9 +639,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
// type deduction and lambdas. For trailing return types resolve the
// decltype expression. Otherwise print the real type when this is
// not a constructor or destructor.
- if ((isa<CXXMethodDecl>(FD) &&
- cast<CXXMethodDecl>(FD)->getParent()->isLambda()) ||
- (FT && FT->getReturnType()->getAs<AutoType>()))
+ if (isa<CXXMethodDecl>(FD) &&
+ cast<CXXMethodDecl>(FD)->getParent()->isLambda())
Proto = "auto " + Proto;
else if (FT && FT->getReturnType()->getAs<DecltypeType>())
FT->getReturnType()
@@ -1252,7 +1290,7 @@ SourceLocation CallExpr::getLocStart() const {
return cast<CXXOperatorCallExpr>(this)->getLocStart();
SourceLocation begin = getCallee()->getLocStart();
- if (begin.isInvalid() && getNumArgs() > 0)
+ if (begin.isInvalid() && getNumArgs() > 0 && getArg(0))
begin = getArg(0)->getLocStart();
return begin;
}
@@ -1261,7 +1299,7 @@ SourceLocation CallExpr::getLocEnd() const {
return cast<CXXOperatorCallExpr>(this)->getLocEnd();
SourceLocation end = getRParenLoc();
- if (end.isInvalid() && getNumArgs() > 0)
+ if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1))
end = getArg(getNumArgs() - 1)->getLocEnd();
return end;
}
@@ -2734,10 +2772,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
if (ILE->getType()->isRecordType()) {
unsigned ElementNo = 0;
RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) {
+ for (const auto *Field : RD->fields()) {
// If this is a union, skip all the fields that aren't being initialized.
- if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
+ if (RD->isUnion() && ILE->getInitializedFieldInUnion() != Field)
continue;
// Don't emit anonymous bitfields, they just affect layout.
@@ -2830,9 +2867,16 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
return false;
}
-bool Expr::HasSideEffects(const ASTContext &Ctx) const {
+bool Expr::HasSideEffects(const ASTContext &Ctx,
+ bool IncludePossibleEffects) const {
+ // In circumstances where we care about definite side effects instead of
+ // potential side effects, we want to ignore expressions that are part of a
+ // macro expansion as a potential side effect.
+ if (!IncludePossibleEffects && getExprLoc().isMacroID())
+ return false;
+
if (isInstantiationDependent())
- return true;
+ return IncludePossibleEffects;
switch (getStmtClass()) {
case NoStmtClass:
@@ -2850,6 +2894,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
case PackExpansionExprClass:
case SubstNonTypeTemplateParmPackExprClass:
case FunctionParmPackExprClass:
+ case TypoExprClass:
+ case CXXFoldExprClass:
llvm_unreachable("shouldn't see dependent / unresolved nodes here");
case DeclRefExprClass:
@@ -2883,21 +2929,27 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
return false;
case CallExprClass:
+ case CXXOperatorCallExprClass:
+ case CXXMemberCallExprClass:
+ case CUDAKernelCallExprClass:
+ case BlockExprClass:
+ case CXXBindTemporaryExprClass:
+ case UserDefinedLiteralClass:
+ // We don't know a call definitely has side effects, but we can check the
+ // call's operands.
+ if (!IncludePossibleEffects)
+ break;
+ return true;
+
case MSPropertyRefExprClass:
case CompoundAssignOperatorClass:
case VAArgExprClass:
case AtomicExprClass:
case StmtExprClass:
- case CXXOperatorCallExprClass:
- case CXXMemberCallExprClass:
- case UserDefinedLiteralClass:
case CXXThrowExprClass:
case CXXNewExprClass:
case CXXDeleteExprClass:
case ExprWithCleanupsClass:
- case CXXBindTemporaryExprClass:
- case BlockExprClass:
- case CUDAKernelCallExprClass:
// These always have a side-effect.
return true;
@@ -2933,25 +2985,29 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
case InitListExprClass:
// FIXME: The children for an InitListExpr doesn't include the array filler.
if (const Expr *E = cast<InitListExpr>(this)->getArrayFiller())
- if (E->HasSideEffects(Ctx))
+ if (E->HasSideEffects(Ctx, IncludePossibleEffects))
return true;
break;
case GenericSelectionExprClass:
return cast<GenericSelectionExpr>(this)->getResultExpr()->
- HasSideEffects(Ctx);
+ HasSideEffects(Ctx, IncludePossibleEffects);
case ChooseExprClass:
- return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(Ctx);
+ return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(
+ Ctx, IncludePossibleEffects);
case CXXDefaultArgExprClass:
- return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(Ctx);
+ return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(
+ Ctx, IncludePossibleEffects);
- case CXXDefaultInitExprClass:
- if (const Expr *E = cast<CXXDefaultInitExpr>(this)->getExpr())
- return E->HasSideEffects(Ctx);
+ case CXXDefaultInitExprClass: {
+ const FieldDecl *FD = cast<CXXDefaultInitExpr>(this)->getField();
+ if (const Expr *E = FD->getInClassInitializer())
+ return E->HasSideEffects(Ctx, IncludePossibleEffects);
// If we've not yet parsed the initializer, assume it has side-effects.
return true;
+ }
case CXXDynamicCastExprClass: {
// A dynamic_cast expression has side-effects if it can throw.
@@ -2966,6 +3022,13 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass:
case CXXFunctionalCastExprClass: {
+ // While volatile reads are side-effecting in both C and C++, we treat them
+ // as having possible (not definite) side-effects. This allows idiomatic
+ // code to behave without warning, such as sizeof(*v) for a volatile-
+ // qualified pointer.
+ if (!IncludePossibleEffects)
+ break;
+
const CastExpr *CE = cast<CastExpr>(this);
if (CE->getCastKind() == CK_LValueToRValue &&
CE->getSubExpr()->getType().isVolatileQualified())
@@ -2981,7 +3044,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
case CXXConstructExprClass:
case CXXTemporaryObjectExprClass: {
const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
- if (!CE->getConstructor()->isTrivial())
+ if (!CE->getConstructor()->isTrivial() && IncludePossibleEffects)
return true;
// A trivial constructor does not add any side-effects of its own. Just look
// at its arguments.
@@ -3009,7 +3072,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
const Expr *Subexpr = *I;
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Subexpr))
Subexpr = OVE->getSourceExpr();
- if (Subexpr->HasSideEffects(Ctx))
+ if (Subexpr->HasSideEffects(Ctx, IncludePossibleEffects))
return true;
}
return false;
@@ -3018,22 +3081,24 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
case ObjCBoxedExprClass:
case ObjCArrayLiteralClass:
case ObjCDictionaryLiteralClass:
- case ObjCMessageExprClass:
case ObjCSelectorExprClass:
case ObjCProtocolExprClass:
- case ObjCPropertyRefExprClass:
case ObjCIsaExprClass:
case ObjCIndirectCopyRestoreExprClass:
case ObjCSubscriptRefExprClass:
case ObjCBridgedCastExprClass:
- // FIXME: Classify these cases better.
- return true;
+ case ObjCMessageExprClass:
+ case ObjCPropertyRefExprClass:
+ // FIXME: Classify these cases better.
+ if (IncludePossibleEffects)
+ return true;
+ break;
}
// Recurse to children.
for (const_child_range SubStmts = children(); SubStmts; ++SubStmts)
if (const Stmt *S = *SubStmts)
- if (cast<Expr>(S)->HasSideEffects(Ctx))
+ if (cast<Expr>(S)->HasSideEffects(Ctx, IncludePossibleEffects))
return true;
return false;
@@ -3279,6 +3344,10 @@ FieldDecl *Expr::getSourceBitField() {
return BinOp->getRHS()->getSourceBitField();
}
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E))
+ if (UnOp->isPrefix() && UnOp->isIncrementDecrementOp())
+ return UnOp->getSubExpr()->getSourceBitField();
+
return nullptr;
}
@@ -3759,7 +3828,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty,
// Compute type- and value-dependence.
Expr *Index = IndexExprs[IndexIdx];
if (Index->isTypeDependent() || Index->isValueDependent())
- ExprBits.ValueDependent = true;
+ ExprBits.TypeDependent = ExprBits.ValueDependent = true;
if (Index->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
// Propagate unexpanded parameter packs.
@@ -3774,7 +3843,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty,
Expr *End = IndexExprs[IndexIdx + 1];
if (Start->isTypeDependent() || Start->isValueDependent() ||
End->isTypeDependent() || End->isValueDependent()) {
- ExprBits.ValueDependent = true;
+ ExprBits.TypeDependent = ExprBits.ValueDependent = true;
ExprBits.InstantiationDependent = true;
} else if (Start->isInstantiationDependent() ||
End->isInstantiationDependent()) {
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
index 64c21dd..9336166 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -909,16 +909,21 @@ LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
case LCK_ByRef:
assert(Var && "capture must have a variable!");
break;
+ case LCK_VLAType:
+ assert(!Var && "VLA type capture cannot have a variable!");
+ Bits |= Capture_ByCopy;
+ break;
}
DeclAndBits.setInt(Bits);
}
LambdaCaptureKind LambdaCapture::getCaptureKind() const {
Decl *D = DeclAndBits.getPointer();
+ bool CapByCopy = DeclAndBits.getInt() & Capture_ByCopy;
if (!D)
- return LCK_This;
+ return CapByCopy ? LCK_VLAType : LCK_This;
- return (DeclAndBits.getInt() & Capture_ByCopy) ? LCK_ByCopy : LCK_ByRef;
+ return CapByCopy ? LCK_ByCopy : LCK_ByRef;
}
LambdaExpr::LambdaExpr(QualType T,
@@ -1073,8 +1078,8 @@ LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const {
"Capture index out-of-range");
VarDecl **IndexVars = getArrayIndexVars();
unsigned *IndexStarts = getArrayIndexStarts();
- return ArrayRef<VarDecl *>(IndexVars + IndexStarts[Index],
- IndexVars + IndexStarts[Index + 1]);
+ return llvm::makeArrayRef(IndexVars + IndexStarts[Index],
+ IndexVars + IndexStarts[Index + 1]);
}
CXXRecordDecl *LambdaExpr::getLambdaClass() const {
@@ -1399,7 +1404,8 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
// It can't be dependent: after all, we were actually able to do the
// lookup.
CXXRecordDecl *Record = nullptr;
- if (getQualifier()) {
+ auto *NNS = getQualifier();
+ if (NNS && NNS->getKind() != NestedNameSpecifier::Super) {
const Type *T = getQualifier()->getAsType();
assert(T && "qualifier in member expression does not name type");
Record = T->getAsCXXRecordDecl();
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
index d3d2530..933ea97 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
@@ -124,10 +124,11 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ObjCPropertyRefExprClass:
// C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of...
case Expr::CXXTypeidExprClass:
- // Unresolved lookups get classified as lvalues.
+ // Unresolved lookups and uncorrected typos get classified as lvalues.
// FIXME: Is this wise? Should they get their own kind?
case Expr::UnresolvedLookupExprClass:
case Expr::UnresolvedMemberExprClass:
+ case Expr::TypoExprClass:
case Expr::CXXDependentScopeMemberExprClass:
case Expr::DependentScopeDeclRefExprClass:
// ObjC instance variables are lvalues
@@ -181,6 +182,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::AsTypeExprClass:
case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::AtomicExprClass:
+ case Expr::CXXFoldExprClass:
return Cl::CL_PRValue;
// Next come the complicated cases.
@@ -613,14 +615,9 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
return Cl::CM_IncompleteType;
// Records with any const fields (recursively) are not modifiable.
- if (const RecordType *R = CT->getAs<RecordType>()) {
- assert((E->getObjectKind() == OK_ObjCProperty ||
- !Ctx.getLangOpts().CPlusPlus) &&
- "C++ struct assignment should be resolved by the "
- "copy assignment operator.");
+ if (const RecordType *R = CT->getAs<RecordType>())
if (R->hasConstFields())
return Cl::CM_ConstQualified;
- }
return Cl::CM_Modifiable;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index 7d7ca99..3d7f2dc 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -201,6 +201,7 @@ namespace {
/// Determine whether this is a one-past-the-end pointer.
bool isOnePastTheEnd() const {
+ assert(!Invalid);
if (IsOnePastTheEnd)
return true;
if (MostDerivedArraySize &&
@@ -1308,7 +1309,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
}
// Does this refer one past the end of some object?
- if (Designator.isOnePastTheEnd()) {
+ if (!Designator.Invalid && Designator.isOnePastTheEnd()) {
const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>();
Info.Diag(Loc, diag::note_constexpr_past_end, 1)
<< !Designator.Entries.empty() << !!VD << VD;
@@ -1328,7 +1329,7 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E,
// C++1y: A constant initializer for an object o [...] may also invoke
// constexpr constructors for o and its subobjects even if those objects
// are of non-literal class types.
- if (Info.getLangOpts().CPlusPlus1y && This &&
+ if (Info.getLangOpts().CPlusPlus14 && This &&
Info.EvaluatingDecl == This->getLValueBase())
return true;
@@ -1421,6 +1422,17 @@ static bool IsWeakLValue(const LValue &Value) {
return Decl && Decl->isWeak();
}
+static bool isZeroSized(const LValue &Value) {
+ const ValueDecl *Decl = GetLValueBaseDecl(Value);
+ if (Decl && isa<VarDecl>(Decl)) {
+ QualType Ty = Decl->getType();
+ if (Ty->isArrayType())
+ return Ty->isIncompleteType() ||
+ Decl->getASTContext().getTypeSize(Ty) == 0;
+ }
+ return false;
+}
+
static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) {
// A null base expression indicates a null pointer. These are always
// evaluatable, and they are false unless the offset is zero.
@@ -2020,7 +2032,9 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived,
/// Extract the value of a character from a string literal.
static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
uint64_t Index) {
- // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
+ // FIXME: Support ObjCEncodeExpr, MakeStringConstant
+ if (auto PE = dyn_cast<PredefinedExpr>(Lit))
+ Lit = PE->getFunctionName();
const StringLiteral *S = cast<StringLiteral>(Lit);
const ConstantArrayType *CAT =
Info.Ctx.getAsConstantArrayType(S->getType());
@@ -2079,6 +2093,64 @@ static void expandArray(APValue &Array, unsigned Index) {
Array.swap(NewValue);
}
+/// Determine whether a type would actually be read by an lvalue-to-rvalue
+/// conversion. If it's of class type, we may assume that the copy operation
+/// is trivial. Note that this is never true for a union type with fields
+/// (because the copy always "reads" the active member) and always true for
+/// a non-class type.
+static bool isReadByLvalueToRvalueConversion(QualType T) {
+ CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+ if (!RD || (RD->isUnion() && !RD->field_empty()))
+ return true;
+ if (RD->isEmpty())
+ return false;
+
+ for (auto *Field : RD->fields())
+ if (isReadByLvalueToRvalueConversion(Field->getType()))
+ return true;
+
+ for (auto &BaseSpec : RD->bases())
+ if (isReadByLvalueToRvalueConversion(BaseSpec.getType()))
+ return true;
+
+ return false;
+}
+
+/// Diagnose an attempt to read from any unreadable field within the specified
+/// type, which might be a class type.
+static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E,
+ QualType T) {
+ CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+ if (!RD)
+ return false;
+
+ if (!RD->hasMutableFields())
+ return false;
+
+ for (auto *Field : RD->fields()) {
+ // If we're actually going to read this field in some way, then it can't
+ // be mutable. If we're in a union, then assigning to a mutable field
+ // (even an empty one) can change the active member, so that's not OK.
+ // FIXME: Add core issue number for the union case.
+ if (Field->isMutable() &&
+ (RD->isUnion() || isReadByLvalueToRvalueConversion(Field->getType()))) {
+ Info.Diag(E, diag::note_constexpr_ltor_mutable, 1) << Field;
+ Info.Note(Field->getLocation(), diag::note_declared_at);
+ return true;
+ }
+
+ if (diagnoseUnreadableFields(Info, E, Field->getType()))
+ return true;
+ }
+
+ for (auto &BaseSpec : RD->bases())
+ if (diagnoseUnreadableFields(Info, E, BaseSpec.getType()))
+ return true;
+
+ // All mutable fields were empty, and thus not actually read.
+ return false;
+}
+
/// Kinds of access we can perform on an object, for diagnostics.
enum AccessKinds {
AK_Read,
@@ -2134,6 +2206,14 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
}
if (I == N) {
+ // If we are reading an object of class type, there may still be more
+ // things we need to check: if there are any mutable subobjects, we
+ // cannot perform this read. (This only happens when performing a trivial
+ // copy or assignment.)
+ if (ObjType->isRecordType() && handler.AccessKind == AK_Read &&
+ diagnoseUnreadableFields(Info, E, ObjType))
+ return handler.failed();
+
if (!handler.found(*O, ObjType))
return false;
@@ -2490,7 +2570,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK,
// Unless we're looking at a local variable or argument in a constexpr call,
// the variable we're reading must be const.
if (!Frame) {
- if (Info.getLangOpts().CPlusPlus1y &&
+ if (Info.getLangOpts().CPlusPlus14 &&
VD == Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()) {
// OK, we can read and modify an object if we're in the process of
// evaluating its initializer, because its lifetime began in this
@@ -2606,7 +2686,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK,
//
// FIXME: Not all local state is mutable. Allow local constant subobjects
// to be read here (but take care with 'mutable' fields).
- if (Frame && Info.getLangOpts().CPlusPlus1y &&
+ if (Frame && Info.getLangOpts().CPlusPlus14 &&
(Info.EvalStatus.HasSideEffects || Info.keepEvaluatingAfterFailure()))
return CompleteObject();
@@ -2648,10 +2728,10 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
return false;
CompleteObject LitObj(&Lit, Base->getType());
return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal);
- } else if (isa<StringLiteral>(Base)) {
+ } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) {
// We represent a string literal array as an lvalue pointing at the
// corresponding expression, rather than building an array of chars.
- // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
+ // FIXME: Support ObjCEncodeExpr, MakeStringConstant
APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0);
CompleteObject StrObj(&Str, Base->getType());
return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal);
@@ -2668,7 +2748,7 @@ static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal,
if (LVal.Designator.Invalid)
return false;
- if (!Info.getLangOpts().CPlusPlus1y) {
+ if (!Info.getLangOpts().CPlusPlus14) {
Info.Diag(E);
return false;
}
@@ -2789,7 +2869,7 @@ static bool handleCompoundAssignment(
if (LVal.Designator.Invalid)
return false;
- if (!Info.getLangOpts().CPlusPlus1y) {
+ if (!Info.getLangOpts().CPlusPlus14) {
Info.Diag(E);
return false;
}
@@ -2938,7 +3018,7 @@ static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal,
if (LVal.Designator.Invalid)
return false;
- if (!Info.getLangOpts().CPlusPlus1y) {
+ if (!Info.getLangOpts().CPlusPlus14) {
Info.Diag(E);
return false;
}
@@ -3588,6 +3668,22 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
return false;
}
+/// Determine if a class has any fields that might need to be copied by a
+/// trivial copy or move operation.
+static bool hasFields(const CXXRecordDecl *RD) {
+ if (!RD || RD->isEmpty())
+ return false;
+ for (auto *FD : RD->fields()) {
+ if (FD->isUnnamedBitfield())
+ continue;
+ return true;
+ }
+ for (auto &Base : RD->bases())
+ if (hasFields(Base.getType()->getAsCXXRecordDecl()))
+ return true;
+ return false;
+}
+
namespace {
typedef SmallVector<APValue, 8> ArgVector;
}
@@ -3626,8 +3722,12 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
// For a trivial copy or move assignment, perform an APValue copy. This is
// essential for unions, where the operations performed by the assignment
// operator cannot be represented as statements.
+ //
+ // Skip this for non-union classes with no fields; in that case, the defaulted
+ // copy/move does not actually read the object.
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee);
- if (MD && MD->isDefaulted() && MD->isTrivial()) {
+ if (MD && MD->isDefaulted() && MD->isTrivial() &&
+ (MD->getParent()->isUnion() || hasFields(MD->getParent()))) {
assert(This &&
(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
LValue RHS;
@@ -3684,11 +3784,18 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
}
// For a trivial copy or move constructor, perform an APValue copy. This is
- // essential for unions, where the operations performed by the constructor
- // cannot be represented by ctor-initializers.
+ // essential for unions (or classes with anonymous union members), where the
+ // operations performed by the constructor cannot be represented by
+ // ctor-initializers.
+ //
+ // Skip this for empty non-union classes; we should not perform an
+ // lvalue-to-rvalue conversion on them because their copy constructor does not
+ // actually read them.
if (Definition->isDefaulted() &&
((Definition->isCopyConstructor() && Definition->isTrivial()) ||
- (Definition->isMoveConstructor() && Definition->isTrivial()))) {
+ (Definition->isMoveConstructor() && Definition->isTrivial())) &&
+ (Definition->getParent()->isUnion() ||
+ hasFields(Definition->getParent()))) {
LValue RHS;
RHS.setFrom(Info.Ctx, ArgValues[0]);
return handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(),
@@ -3985,7 +4092,7 @@ public:
const FunctionDecl *FD = nullptr;
LValue *This = nullptr, ThisVal;
- ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs());
+ auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
bool HasQualifier = false;
// Extract function decl and 'this' pointer from the callee.
@@ -4148,7 +4255,7 @@ public:
return VisitUnaryPostIncDec(UO);
}
bool VisitUnaryPostIncDec(const UnaryOperator *UO) {
- if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure())
+ if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())
return Error(UO);
LValue LVal;
@@ -4573,7 +4680,7 @@ bool LValueExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
}
bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) {
- if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure())
+ if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())
return Error(UO);
if (!this->Visit(UO->getSubExpr()))
@@ -4586,7 +4693,7 @@ bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) {
bool LValueExprEvaluator::VisitCompoundAssignOperator(
const CompoundAssignOperator *CAO) {
- if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure())
+ if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())
return Error(CAO);
APValue RHS;
@@ -4608,7 +4715,7 @@ bool LValueExprEvaluator::VisitCompoundAssignOperator(
}
bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
- if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure())
+ if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())
return Error(E);
APValue NewVal;
@@ -4733,6 +4840,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
case CK_CPointerToObjCPointerCast:
case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
+ case CK_AddressSpaceConversion:
if (!Visit(SubExpr))
return false;
// Bitcasts to cv void* are static_casts, not reinterpret_casts, so are
@@ -4818,6 +4926,38 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
return ExprEvaluatorBaseTy::VisitCastExpr(E);
}
+static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) {
+ // C++ [expr.alignof]p3:
+ // When alignof is applied to a reference type, the result is the
+ // alignment of the referenced type.
+ if (const ReferenceType *Ref = T->getAs<ReferenceType>())
+ T = Ref->getPointeeType();
+
+ // __alignof is defined to return the preferred alignment.
+ return Info.Ctx.toCharUnitsFromBits(
+ Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
+}
+
+static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) {
+ E = E->IgnoreParens();
+
+ // The kinds of expressions that we have special-case logic here for
+ // should be kept up to date with the special checks for those
+ // expressions in Sema.
+
+ // alignof decl is always accepted, even if it doesn't make sense: we default
+ // to 1 in those cases.
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ return Info.Ctx.getDeclAlign(DRE->getDecl(),
+ /*RefAsPointee*/true);
+
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ return Info.Ctx.getDeclAlign(ME->getMemberDecl(),
+ /*RefAsPointee*/true);
+
+ return GetAlignOfType(Info, E->getType());
+}
+
bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (IsStringLiteralCall(E))
return Success(E);
@@ -4825,7 +4965,71 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
switch (E->getBuiltinCallee()) {
case Builtin::BI__builtin_addressof:
return EvaluateLValue(E->getArg(0), Result, Info);
+ case Builtin::BI__builtin_assume_aligned: {
+ // We need to be very careful here because: if the pointer does not have the
+ // asserted alignment, then the behavior is undefined, and undefined
+ // behavior is non-constant.
+ if (!EvaluatePointer(E->getArg(0), Result, Info))
+ return false;
+
+ LValue OffsetResult(Result);
+ APSInt Alignment;
+ if (!EvaluateInteger(E->getArg(1), Alignment, Info))
+ return false;
+ CharUnits Align = CharUnits::fromQuantity(getExtValue(Alignment));
+
+ if (E->getNumArgs() > 2) {
+ APSInt Offset;
+ if (!EvaluateInteger(E->getArg(2), Offset, Info))
+ return false;
+
+ int64_t AdditionalOffset = -getExtValue(Offset);
+ OffsetResult.Offset += CharUnits::fromQuantity(AdditionalOffset);
+ }
+
+ // If there is a base object, then it must have the correct alignment.
+ if (OffsetResult.Base) {
+ CharUnits BaseAlignment;
+ if (const ValueDecl *VD =
+ OffsetResult.Base.dyn_cast<const ValueDecl*>()) {
+ BaseAlignment = Info.Ctx.getDeclAlign(VD);
+ } else {
+ BaseAlignment =
+ GetAlignOfExpr(Info, OffsetResult.Base.get<const Expr*>());
+ }
+
+ if (BaseAlignment < Align) {
+ Result.Designator.setInvalid();
+ // FIXME: Quantities here cast to integers because the plural modifier
+ // does not work on APSInts yet.
+ CCEDiag(E->getArg(0),
+ diag::note_constexpr_baa_insufficient_alignment) << 0
+ << (int) BaseAlignment.getQuantity()
+ << (unsigned) getExtValue(Alignment);
+ return false;
+ }
+ }
+
+ // The offset must also have the correct alignment.
+ if (OffsetResult.Offset.RoundUpToAlignment(Align) != OffsetResult.Offset) {
+ Result.Designator.setInvalid();
+ APSInt Offset(64, false);
+ Offset = OffsetResult.Offset.getQuantity();
+ if (OffsetResult.Base)
+ CCEDiag(E->getArg(0),
+ diag::note_constexpr_baa_insufficient_alignment) << 1
+ << (int) getExtValue(Offset) << (unsigned) getExtValue(Alignment);
+ else
+ CCEDiag(E->getArg(0),
+ diag::note_constexpr_baa_value_insufficient_alignment)
+ << Offset << (unsigned) getExtValue(Alignment);
+
+ return false;
+ }
+
+ return true;
+ }
default:
return ExprEvaluatorBaseTy::VisitCallExpr(E);
}
@@ -5166,7 +5370,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
if (ZeroInit && !ZeroInitialization(E))
return false;
- ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs());
+ auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
return HandleConstructorCall(E->getExprLoc(), This, Args,
cast<CXXConstructorDecl>(Definition), Info,
Result);
@@ -5270,6 +5474,9 @@ public:
bool VisitCallExpr(const CallExpr *E) {
return VisitConstructExpr(E);
}
+ bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) {
+ return VisitConstructExpr(E);
+ }
};
} // end anonymous namespace
@@ -5645,7 +5852,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
return false;
}
- ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs());
+ auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
return HandleConstructorCall(E->getExprLoc(), Subobject, Args,
cast<CXXConstructorDecl>(Definition),
Info, *Value);
@@ -5786,8 +5993,6 @@ public:
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
private:
- CharUnits GetAlignOfExpr(const Expr *E);
- CharUnits GetAlignOfType(QualType T);
static QualType GetObjectType(APValue::LValueBase B);
bool TryEvaluateBuiltinObjectSize(const CallExpr *E);
// FIXME: Missing: array subscript of vector, member of vector
@@ -5985,8 +6190,20 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) {
return false;
}
- // If we can prove the base is null, lower to zero now.
- if (!Base.getLValueBase()) return Success(0, E);
+ if (!Base.getLValueBase()) {
+ // It is not possible to determine which objects ptr points to at compile time,
+ // __builtin_object_size should return (size_t) -1 for type 0 or 1
+ // and (size_t) 0 for type 2 or 3.
+ llvm::APSInt TypeIntVaue;
+ const Expr *ExprType = E->getArg(1);
+ if (!ExprType->EvaluateAsInt(TypeIntVaue, Info.Ctx))
+ return false;
+ if (TypeIntVaue == 0 || TypeIntVaue == 1)
+ return Success(-1, E);
+ if (TypeIntVaue == 2 || TypeIntVaue == 3)
+ return Success(0, E);
+ return Error(E);
+ }
QualType T = GetObjectType(Base.getLValueBase());
if (T.isNull() ||
@@ -6286,6 +6503,27 @@ static bool HasSameBase(const LValue &A, const LValue &B) {
A.getLValueCallIndex() == B.getLValueCallIndex();
}
+/// \brief Determine whether this is a pointer past the end of the complete
+/// object referred to by the lvalue.
+static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx,
+ const LValue &LV) {
+ // A null pointer can be viewed as being "past the end" but we don't
+ // choose to look at it that way here.
+ if (!LV.getLValueBase())
+ return false;
+
+ // If the designator is valid and refers to a subobject, we're not pointing
+ // past the end.
+ if (!LV.getLValueDesignator().Invalid &&
+ !LV.getLValueDesignator().isOnePastTheEnd())
+ return false;
+
+ // We're a past-the-end pointer if we point to the byte after the object,
+ // no matter what our type or path is.
+ auto Size = Ctx.getTypeSizeInChars(getType(LV.getLValueBase()));
+ return LV.getLValueOffset() == Size;
+}
+
namespace {
/// \brief Data recursive integer evaluator of certain binary operators.
@@ -6605,15 +6843,27 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
QualType LHSTy = E->getLHS()->getType();
QualType RHSTy = E->getRHS()->getType();
- if (LHSTy->isAnyComplexType()) {
- assert(RHSTy->isAnyComplexType() && "Invalid comparison");
+ if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) {
ComplexValue LHS, RHS;
-
- bool LHSOK = EvaluateComplex(E->getLHS(), LHS, Info);
+ bool LHSOK;
+ if (E->getLHS()->getType()->isRealFloatingType()) {
+ LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info);
+ if (LHSOK) {
+ LHS.makeComplexFloat();
+ LHS.FloatImag = APFloat(LHS.FloatReal.getSemantics());
+ }
+ } else {
+ LHSOK = EvaluateComplex(E->getLHS(), LHS, Info);
+ }
if (!LHSOK && !Info.keepEvaluatingAfterFailure())
return false;
- if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK)
+ if (E->getRHS()->getType()->isRealFloatingType()) {
+ if (!EvaluateFloat(E->getRHS(), RHS.FloatReal, Info) || !LHSOK)
+ return false;
+ RHS.makeComplexFloat();
+ RHS.FloatImag = APFloat(RHS.FloatReal.getSemantics());
+ } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK)
return false;
if (LHS.isComplexFloat()) {
@@ -6736,6 +6986,18 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// object.
if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue))
return Error(E);
+ // We can't compare the address of the start of one object with the
+ // past-the-end address of another object, per C++ DR1652.
+ if ((LHSValue.Base && LHSValue.Offset.isZero() &&
+ isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) ||
+ (RHSValue.Base && RHSValue.Offset.isZero() &&
+ isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue)))
+ return Error(E);
+ // We can't tell whether an object is at the same address as another
+ // zero sized object.
+ if ((RHSValue.Base && isZeroSized(LHSValue)) ||
+ (LHSValue.Base && isZeroSized(RHSValue)))
+ return Error(E);
// Pointers with different bases cannot represent the same object.
// (Note that clang defaults to -fmerge-all-constants, which can
// lead to inconsistent results for comparisons involving the address
@@ -6940,39 +7202,6 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
return ExprEvaluatorBaseTy::VisitBinaryOperator(E);
}
-CharUnits IntExprEvaluator::GetAlignOfType(QualType T) {
- // C++ [expr.alignof]p3:
- // When alignof is applied to a reference type, the result is the
- // alignment of the referenced type.
- if (const ReferenceType *Ref = T->getAs<ReferenceType>())
- T = Ref->getPointeeType();
-
- // __alignof is defined to return the preferred alignment.
- return Info.Ctx.toCharUnitsFromBits(
- Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
-}
-
-CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
- E = E->IgnoreParens();
-
- // The kinds of expressions that we have special-case logic here for
- // should be kept up to date with the special checks for those
- // expressions in Sema.
-
- // alignof decl is always accepted, even if it doesn't make sense: we default
- // to 1 in those cases.
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- return Info.Ctx.getDeclAlign(DRE->getDecl(),
- /*RefAsPointee*/true);
-
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
- return Info.Ctx.getDeclAlign(ME->getMemberDecl(),
- /*RefAsPointee*/true);
-
- return GetAlignOfType(E->getType());
-}
-
-
/// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with
/// a result as the expression's type.
bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
@@ -6980,9 +7209,9 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
switch(E->getKind()) {
case UETT_AlignOf: {
if (E->isArgumentType())
- return Success(GetAlignOfType(E->getArgumentType()), E);
+ return Success(GetAlignOfType(Info, E->getArgumentType()), E);
else
- return Success(GetAlignOfExpr(E->getArgumentExpr()), E);
+ return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E);
}
case UETT_VecStep: {
@@ -7732,24 +7961,49 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma)
return ExprEvaluatorBaseTy::VisitBinaryOperator(E);
- bool LHSOK = Visit(E->getLHS());
+ // Track whether the LHS or RHS is real at the type system level. When this is
+ // the case we can simplify our evaluation strategy.
+ bool LHSReal = false, RHSReal = false;
+
+ bool LHSOK;
+ if (E->getLHS()->getType()->isRealFloatingType()) {
+ LHSReal = true;
+ APFloat &Real = Result.FloatReal;
+ LHSOK = EvaluateFloat(E->getLHS(), Real, Info);
+ if (LHSOK) {
+ Result.makeComplexFloat();
+ Result.FloatImag = APFloat(Real.getSemantics());
+ }
+ } else {
+ LHSOK = Visit(E->getLHS());
+ }
if (!LHSOK && !Info.keepEvaluatingAfterFailure())
return false;
ComplexValue RHS;
- if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK)
+ if (E->getRHS()->getType()->isRealFloatingType()) {
+ RHSReal = true;
+ APFloat &Real = RHS.FloatReal;
+ if (!EvaluateFloat(E->getRHS(), Real, Info) || !LHSOK)
+ return false;
+ RHS.makeComplexFloat();
+ RHS.FloatImag = APFloat(Real.getSemantics());
+ } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK)
return false;
- assert(Result.isComplexFloat() == RHS.isComplexFloat() &&
- "Invalid operands to binary operator.");
+ assert(!(LHSReal && RHSReal) &&
+ "Cannot have both operands of a complex operation be real.");
switch (E->getOpcode()) {
default: return Error(E);
case BO_Add:
if (Result.isComplexFloat()) {
Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),
APFloat::rmNearestTiesToEven);
- Result.getComplexFloatImag().add(RHS.getComplexFloatImag(),
- APFloat::rmNearestTiesToEven);
+ if (LHSReal)
+ Result.getComplexFloatImag() = RHS.getComplexFloatImag();
+ else if (!RHSReal)
+ Result.getComplexFloatImag().add(RHS.getComplexFloatImag(),
+ APFloat::rmNearestTiesToEven);
} else {
Result.getComplexIntReal() += RHS.getComplexIntReal();
Result.getComplexIntImag() += RHS.getComplexIntImag();
@@ -7759,8 +8013,13 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (Result.isComplexFloat()) {
Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),
APFloat::rmNearestTiesToEven);
- Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(),
- APFloat::rmNearestTiesToEven);
+ if (LHSReal) {
+ Result.getComplexFloatImag() = RHS.getComplexFloatImag();
+ Result.getComplexFloatImag().changeSign();
+ } else if (!RHSReal) {
+ Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(),
+ APFloat::rmNearestTiesToEven);
+ }
} else {
Result.getComplexIntReal() -= RHS.getComplexIntReal();
Result.getComplexIntImag() -= RHS.getComplexIntImag();
@@ -7768,25 +8027,75 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
break;
case BO_Mul:
if (Result.isComplexFloat()) {
+ // This is an implementation of complex multiplication according to the
+ // constraints laid out in C11 Annex G. The implemantion uses the
+ // following naming scheme:
+ // (a + ib) * (c + id)
ComplexValue LHS = Result;
- APFloat &LHS_r = LHS.getComplexFloatReal();
- APFloat &LHS_i = LHS.getComplexFloatImag();
- APFloat &RHS_r = RHS.getComplexFloatReal();
- APFloat &RHS_i = RHS.getComplexFloatImag();
-
- APFloat Tmp = LHS_r;
- Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven);
- Result.getComplexFloatReal() = Tmp;
- Tmp = LHS_i;
- Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
- Result.getComplexFloatReal().subtract(Tmp, APFloat::rmNearestTiesToEven);
-
- Tmp = LHS_r;
- Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
- Result.getComplexFloatImag() = Tmp;
- Tmp = LHS_i;
- Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven);
- Result.getComplexFloatImag().add(Tmp, APFloat::rmNearestTiesToEven);
+ APFloat &A = LHS.getComplexFloatReal();
+ APFloat &B = LHS.getComplexFloatImag();
+ APFloat &C = RHS.getComplexFloatReal();
+ APFloat &D = RHS.getComplexFloatImag();
+ APFloat &ResR = Result.getComplexFloatReal();
+ APFloat &ResI = Result.getComplexFloatImag();
+ if (LHSReal) {
+ assert(!RHSReal && "Cannot have two real operands for a complex op!");
+ ResR = A * C;
+ ResI = A * D;
+ } else if (RHSReal) {
+ ResR = C * A;
+ ResI = C * B;
+ } else {
+ // In the fully general case, we need to handle NaNs and infinities
+ // robustly.
+ APFloat AC = A * C;
+ APFloat BD = B * D;
+ APFloat AD = A * D;
+ APFloat BC = B * C;
+ ResR = AC - BD;
+ ResI = AD + BC;
+ if (ResR.isNaN() && ResI.isNaN()) {
+ bool Recalc = false;
+ if (A.isInfinity() || B.isInfinity()) {
+ A = APFloat::copySign(
+ APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A);
+ B = APFloat::copySign(
+ APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B);
+ if (C.isNaN())
+ C = APFloat::copySign(APFloat(C.getSemantics()), C);
+ if (D.isNaN())
+ D = APFloat::copySign(APFloat(D.getSemantics()), D);
+ Recalc = true;
+ }
+ if (C.isInfinity() || D.isInfinity()) {
+ C = APFloat::copySign(
+ APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C);
+ D = APFloat::copySign(
+ APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D);
+ if (A.isNaN())
+ A = APFloat::copySign(APFloat(A.getSemantics()), A);
+ if (B.isNaN())
+ B = APFloat::copySign(APFloat(B.getSemantics()), B);
+ Recalc = true;
+ }
+ if (!Recalc && (AC.isInfinity() || BD.isInfinity() ||
+ AD.isInfinity() || BC.isInfinity())) {
+ if (A.isNaN())
+ A = APFloat::copySign(APFloat(A.getSemantics()), A);
+ if (B.isNaN())
+ B = APFloat::copySign(APFloat(B.getSemantics()), B);
+ if (C.isNaN())
+ C = APFloat::copySign(APFloat(C.getSemantics()), C);
+ if (D.isNaN())
+ D = APFloat::copySign(APFloat(D.getSemantics()), D);
+ Recalc = true;
+ }
+ if (Recalc) {
+ ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D);
+ ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C);
+ }
+ }
+ }
} else {
ComplexValue LHS = Result;
Result.getComplexIntReal() =
@@ -7799,33 +8108,57 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
break;
case BO_Div:
if (Result.isComplexFloat()) {
+ // This is an implementation of complex division according to the
+ // constraints laid out in C11 Annex G. The implemantion uses the
+ // following naming scheme:
+ // (a + ib) / (c + id)
ComplexValue LHS = Result;
- APFloat &LHS_r = LHS.getComplexFloatReal();
- APFloat &LHS_i = LHS.getComplexFloatImag();
- APFloat &RHS_r = RHS.getComplexFloatReal();
- APFloat &RHS_i = RHS.getComplexFloatImag();
- APFloat &Res_r = Result.getComplexFloatReal();
- APFloat &Res_i = Result.getComplexFloatImag();
-
- APFloat Den = RHS_r;
- Den.multiply(RHS_r, APFloat::rmNearestTiesToEven);
- APFloat Tmp = RHS_i;
- Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
- Den.add(Tmp, APFloat::rmNearestTiesToEven);
-
- Res_r = LHS_r;
- Res_r.multiply(RHS_r, APFloat::rmNearestTiesToEven);
- Tmp = LHS_i;
- Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
- Res_r.add(Tmp, APFloat::rmNearestTiesToEven);
- Res_r.divide(Den, APFloat::rmNearestTiesToEven);
-
- Res_i = LHS_i;
- Res_i.multiply(RHS_r, APFloat::rmNearestTiesToEven);
- Tmp = LHS_r;
- Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
- Res_i.subtract(Tmp, APFloat::rmNearestTiesToEven);
- Res_i.divide(Den, APFloat::rmNearestTiesToEven);
+ APFloat &A = LHS.getComplexFloatReal();
+ APFloat &B = LHS.getComplexFloatImag();
+ APFloat &C = RHS.getComplexFloatReal();
+ APFloat &D = RHS.getComplexFloatImag();
+ APFloat &ResR = Result.getComplexFloatReal();
+ APFloat &ResI = Result.getComplexFloatImag();
+ if (RHSReal) {
+ ResR = A / C;
+ ResI = B / C;
+ } else {
+ if (LHSReal) {
+ // No real optimizations we can do here, stub out with zero.
+ B = APFloat::getZero(A.getSemantics());
+ }
+ int DenomLogB = 0;
+ APFloat MaxCD = maxnum(abs(C), abs(D));
+ if (MaxCD.isFinite()) {
+ DenomLogB = ilogb(MaxCD);
+ C = scalbn(C, -DenomLogB);
+ D = scalbn(D, -DenomLogB);
+ }
+ APFloat Denom = C * C + D * D;
+ ResR = scalbn((A * C + B * D) / Denom, -DenomLogB);
+ ResI = scalbn((B * C - A * D) / Denom, -DenomLogB);
+ if (ResR.isNaN() && ResI.isNaN()) {
+ if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) {
+ ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A;
+ ResI = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * B;
+ } else if ((A.isInfinity() || B.isInfinity()) && C.isFinite() &&
+ D.isFinite()) {
+ A = APFloat::copySign(
+ APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A);
+ B = APFloat::copySign(
+ APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B);
+ ResR = APFloat::getInf(ResR.getSemantics()) * (A * C + B * D);
+ ResI = APFloat::getInf(ResI.getSemantics()) * (B * C - A * D);
+ } else if (MaxCD.isInfinity() && A.isFinite() && B.isFinite()) {
+ C = APFloat::copySign(
+ APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C);
+ D = APFloat::copySign(
+ APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D);
+ ResR = APFloat::getZero(ResR.getSemantics()) * (A * C + B * D);
+ ResI = APFloat::getZero(ResI.getSemantics()) * (B * C - A * D);
+ }
+ }
+ }
} else {
if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0)
return Error(E, diag::note_expr_divide_by_zero);
@@ -7966,6 +8299,7 @@ public:
default:
return ExprEvaluatorBaseTy::VisitCallExpr(E);
case Builtin::BI__assume:
+ case Builtin::BI__builtin_assume:
// The argument is not evaluated!
return true;
}
@@ -8338,6 +8672,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CXXDeleteExprClass:
case Expr::CXXPseudoDestructorExprClass:
case Expr::UnresolvedLookupExprClass:
+ case Expr::TypoExprClass:
case Expr::DependentScopeDeclRefExprClass:
case Expr::CXXConstructExprClass:
case Expr::CXXStdInitializerListExprClass:
@@ -8373,6 +8708,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::PseudoObjectExprClass:
case Expr::AtomicExprClass:
case Expr::LambdaExprClass:
+ case Expr::CXXFoldExprClass:
return ICEDiag(IK_NotICE, E->getLocStart());
case Expr::InitListExprClass: {
@@ -8682,7 +9018,11 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx,
if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc))
return false;
- assert(Result.isInt() && "pointer cast to int is not an ICE");
+ if (!Result.isInt()) {
+ if (Loc) *Loc = E->getExprLoc();
+ return false;
+ }
+
if (Value) *Value = Result.getInt();
return true;
}
@@ -8751,7 +9091,8 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
ArgVector ArgValues(Args.size());
for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end();
I != E; ++I) {
- if (!Evaluate(ArgValues[I - Args.begin()], Info, *I))
+ if ((*I)->isValueDependent() ||
+ !Evaluate(ArgValues[I - Args.begin()], Info, *I))
// If evaluation fails, throw away the argument entirely.
ArgValues[I - Args.begin()] = APValue();
if (Info.EvalStatus.HasSideEffects)
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
index b5f8c0f..378121c 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
@@ -29,16 +29,64 @@ using namespace clang;
namespace {
+/// According to Itanium C++ ABI 5.1.2:
+/// the name of an anonymous union is considered to be
+/// the name of the first named data member found by a pre-order,
+/// depth-first, declaration-order walk of the data members of
+/// the anonymous union.
+/// If there is no such data member (i.e., if all of the data members
+/// in the union are unnamed), then there is no way for a program to
+/// refer to the anonymous union, and there is therefore no need to mangle its name.
+///
+/// Returns the name of anonymous union VarDecl or nullptr if it is not found.
+static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) {
+ const RecordType *RT = VD.getType()->getAs<RecordType>();
+ assert(RT && "type of VarDecl is expected to be RecordType.");
+ assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union.");
+ if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) {
+ return FD->getIdentifier();
+ }
+
+ return nullptr;
+}
+
/// \brief Keeps track of the mangled names of lambda expressions and block
/// literals within a particular context.
class ItaniumNumberingContext : public MangleNumberingContext {
- llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers;
- llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers;
+ llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
+ llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers;
+ llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers;
public:
+ unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
+ const FunctionProtoType *Proto =
+ CallOperator->getType()->getAs<FunctionProtoType>();
+ ASTContext &Context = CallOperator->getASTContext();
+
+ QualType Key =
+ Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(),
+ FunctionProtoType::ExtProtoInfo());
+ Key = Context.getCanonicalType(Key);
+ return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
+ }
+
+ unsigned getManglingNumber(const BlockDecl *BD) override {
+ const Type *Ty = nullptr;
+ return ++ManglingNumbers[Ty];
+ }
+
+ unsigned getStaticLocalNumber(const VarDecl *VD) override {
+ return 0;
+ }
+
/// Variable decls are numbered by identifier.
unsigned getManglingNumber(const VarDecl *VD, unsigned) override {
- return ++VarManglingNumbers[VD->getIdentifier()];
+ const IdentifierInfo *Identifier = VD->getIdentifier();
+ if (!Identifier) {
+ // VarDecl without an identifier represents an anonymous union declaration.
+ Identifier = findAnonymousUnionVarDeclName(*VD);
+ }
+ return ++VarManglingNumbers[Identifier];
}
unsigned getManglingNumber(const TagDecl *TD, unsigned) override {
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
index 977d6fc..156ad64 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
@@ -117,7 +117,7 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy;
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
-
+
public:
explicit ItaniumMangleContextImpl(ASTContext &Context,
DiagnosticsEngine &Diags)
@@ -150,6 +150,8 @@ public:
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
raw_ostream &) override;
+ void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override;
+ void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override;
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) override;
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
@@ -373,6 +375,7 @@ private:
NamedDecl *firstQualifierLookup,
DeclarationName name,
unsigned knownArity);
+ void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
@@ -634,13 +637,11 @@ void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {
return;
// <template-template-param> ::= <template-param>
- if (const TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(ND)) {
+ if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND))
mangleTemplateParameter(TTP->getIndex());
- return;
- }
+ else
+ mangleUnscopedName(ND->getTemplatedDecl());
- mangleUnscopedName(ND->getTemplatedDecl());
addSubstitution(ND);
}
@@ -811,6 +812,9 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
// We never want an 'E' here.
return;
+ case NestedNameSpecifier::Super:
+ llvm_unreachable("Can't mangle __super specifier");
+
case NestedNameSpecifier::Namespace:
if (qualifier->getPrefix())
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
@@ -1046,24 +1050,6 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
mangleUnqualifiedName(nullptr, name, knownArity);
}
-static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) {
- assert(RD->isAnonymousStructOrUnion() &&
- "Expected anonymous struct or union!");
-
- for (const auto *I : RD->fields()) {
- if (I->getIdentifier())
- return I;
-
- if (const RecordType *RT = I->getType()->getAs<RecordType>())
- if (const FieldDecl *NamedDataMember =
- FindFirstNamedDataMember(RT->getDecl()))
- return NamedDataMember;
- }
-
- // We didn't find a named data member.
- return nullptr;
-}
-
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
DeclarationName Name,
unsigned KnownArity) {
@@ -1100,9 +1086,9 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
// We must have an anonymous union or struct declaration.
- const RecordDecl *RD =
+ const RecordDecl *RD =
cast<RecordDecl>(VD->getType()->getAs<RecordType>()->getDecl());
-
+
// Itanium C++ ABI 5.1.2:
//
// For the purposes of mangling, the name of an anonymous union is
@@ -1112,14 +1098,16 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// the data members in the union are unnamed), then there is no way for
// a program to refer to the anonymous union, and there is therefore no
// need to mangle its name.
- const FieldDecl *FD = FindFirstNamedDataMember(RD);
+ assert(RD->isAnonymousStructOrUnion()
+ && "Expected anonymous struct or union!");
+ const FieldDecl *FD = RD->findFirstNamedDataMember();
// It's actually possible for various reasons for us to get here
// with an empty anonymous struct / union. Fortunately, it
// doesn't really matter what name we generate.
if (!FD) break;
assert(FD->getIdentifier() && "Data member name isn't an identifier!");
-
+
mangleSourceName(FD->getIdentifier());
break;
}
@@ -1409,8 +1397,8 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
if (!Number)
Number = Context.getBlockId(Block, false);
Out << "Ub";
- if (Number > 1)
- Out << Number - 2;
+ if (Number > 0)
+ Out << Number - 1;
Out << '_';
}
@@ -1459,6 +1447,9 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
// nothing
return;
+ case NestedNameSpecifier::Super:
+ llvm_unreachable("Can't mangle __super specifier");
+
case NestedNameSpecifier::Namespace:
mangleName(qualifier->getAsNamespace());
return;
@@ -1554,14 +1545,13 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND,
return;
// <template-template-param> ::= <template-param>
- if (const TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(ND)) {
+ if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
mangleTemplateParameter(TTP->getIndex());
- return;
+ } else {
+ manglePrefix(getEffectiveDeclContext(ND), NoFunction);
+ mangleUnqualifiedName(ND->getTemplatedDecl());
}
- manglePrefix(getEffectiveDeclContext(ND), NoFunction);
- mangleUnqualifiedName(ND->getTemplatedDecl());
addSubstitution(ND);
}
@@ -1834,6 +1824,19 @@ void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
Context.mangleObjCMethodName(MD, Out);
}
+static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty) {
+ if (Quals)
+ return true;
+ if (Ty->isSpecificBuiltinType(BuiltinType::ObjCSel))
+ return true;
+ if (Ty->isOpenCLSpecificType())
+ return true;
+ if (Ty->isBuiltinType())
+ return false;
+
+ return true;
+}
+
void CXXNameMangler::mangleType(QualType T) {
// If our type is instantiation-dependent but not dependent, we mangle
// it as it was written in the source, removing any top-level sugar.
@@ -1875,7 +1878,7 @@ void CXXNameMangler::mangleType(QualType T) {
Qualifiers quals = split.Quals;
const Type *ty = split.Ty;
- bool isSubstitutable = quals || !isa<BuiltinType>(T);
+ bool isSubstitutable = isTypeSubstitutable(quals, ty);
if (isSubstitutable && mangleSubstitution(T))
return;
@@ -2301,9 +2304,7 @@ void CXXNameMangler::mangleType(const VectorType *T) {
llvm::Triple::ArchType Arch =
getASTContext().getTargetInfo().getTriple().getArch();
if ((Arch == llvm::Triple::aarch64 ||
- Arch == llvm::Triple::aarch64_be ||
- Arch == llvm::Triple::arm64_be ||
- Arch == llvm::Triple::arm64) && !Target.isOSDarwin())
+ Arch == llvm::Triple::aarch64_be) && !Target.isOSDarwin())
mangleAArch64NeonVectorType(T);
else
mangleNeonVectorType(T);
@@ -2528,6 +2529,18 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
if (base) {
+
+ // Ignore member expressions involving anonymous unions.
+ while (const auto *RT = base->getType()->getAs<RecordType>()) {
+ if (!RT->getDecl()->isAnonymousStructOrUnion())
+ break;
+ const auto *ME = dyn_cast<MemberExpr>(base);
+ if (!ME)
+ break;
+ base = ME->getBase();
+ isArrow = ME->isArrow();
+ }
+
if (base->isImplicitCXXThis()) {
// Note: GCC mangles member expressions to the implicit 'this' as
// *this., whereas we represent them as this->. The Itanium C++ ABI
@@ -2572,12 +2585,23 @@ static bool isParenthesizedADLCallee(const CallExpr *call) {
return true;
}
+void CXXNameMangler::mangleCastExpression(const Expr *E, StringRef CastEncoding) {
+ const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);
+ Out << CastEncoding;
+ mangleType(ECE->getType());
+ mangleExpression(ECE->getSubExpr());
+}
+
void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
// ::= <trinary operator-name> <expression> <expression> <expression>
// ::= cv <type> expression # conversion with one argument
// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
+ // ::= dc <type> <expression> # dynamic_cast<type> (expression)
+ // ::= sc <type> <expression> # static_cast<type> (expression)
+ // ::= cc <type> <expression> # const_cast<type> (expression)
+ // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
// ::= st <type> # sizeof (a type)
// ::= at <type> # alignof (a type)
// ::= <template-param>
@@ -2612,6 +2636,7 @@ recurse:
case Expr::ParenListExprClass:
case Expr::LambdaExprClass:
case Expr::MSPropertyRefExprClass:
+ case Expr::TypoExprClass: // This should no longer exist in the AST by now.
llvm_unreachable("unexpected statement kind");
// FIXME: invent manglings for all these.
@@ -2643,7 +2668,6 @@ recurse:
case Expr::ArrayTypeTraitExprClass:
case Expr::ExpressionTraitExprClass:
case Expr::VAArgExprClass:
- case Expr::CXXUuidofExprClass:
case Expr::CUDAKernelCallExprClass:
case Expr::AsTypeExprClass:
case Expr::PseudoObjectExprClass:
@@ -2658,6 +2682,20 @@ recurse:
break;
}
+ case Expr::CXXUuidofExprClass: {
+ const CXXUuidofExpr *UE = cast<CXXUuidofExpr>(E);
+ if (UE->isTypeOperand()) {
+ QualType UuidT = UE->getTypeOperand(Context.getASTContext());
+ Out << "u8__uuidoft";
+ mangleType(UuidT);
+ } else {
+ Expr *UuidExp = UE->getExprOperand();
+ Out << "u8__uuidofz";
+ mangleExpression(UuidExp, Arity);
+ }
+ break;
+ }
+
// Even gcc-4.5 doesn't mangle this.
case Expr::BinaryConditionalOperatorClass: {
DiagnosticsEngine &Diags = Context.getDiags();
@@ -2982,17 +3020,22 @@ recurse:
// Fall through to mangle the cast itself.
case Expr::CStyleCastExprClass:
+ case Expr::CXXFunctionalCastExprClass:
+ mangleCastExpression(E, "cv");
+ break;
+
case Expr::CXXStaticCastExprClass:
+ mangleCastExpression(E, "sc");
+ break;
case Expr::CXXDynamicCastExprClass:
+ mangleCastExpression(E, "dc");
+ break;
case Expr::CXXReinterpretCastExprClass:
+ mangleCastExpression(E, "rc");
+ break;
case Expr::CXXConstCastExprClass:
- case Expr::CXXFunctionalCastExprClass: {
- const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);
- Out << "cv";
- mangleType(ECE->getType());
- mangleExpression(ECE->getSubExpr());
+ mangleCastExpression(E, "cc");
break;
- }
case Expr::CXXOperatorCallExprClass: {
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
@@ -3175,12 +3218,33 @@ recurse:
mangleFunctionParam(cast<ParmVarDecl>(Pack));
break;
}
-
+
case Expr::MaterializeTemporaryExprClass: {
mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
break;
}
-
+
+ case Expr::CXXFoldExprClass: {
+ auto *FE = cast<CXXFoldExpr>(E);
+ if (FE->isLeftFold())
+ Out << (FE->getInit() ? "fL" : "fl");
+ else
+ Out << (FE->getInit() ? "fR" : "fr");
+
+ if (FE->getOperator() == BO_PtrMemD)
+ Out << "ds";
+ else
+ mangleOperatorName(
+ BinaryOperator::getOverloadedOperator(FE->getOperator()),
+ /*Arity=*/2);
+
+ if (FE->getLHS())
+ mangleExpression(FE->getLHS());
+ if (FE->getRHS())
+ mangleExpression(FE->getRHS());
+ break;
+ }
+
case Expr::CXXThisExprClass:
Out << "fpT";
break;
@@ -3251,8 +3315,8 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
// <ctor-dtor-name> ::= C1 # complete object constructor
// ::= C2 # base object constructor
- // ::= C3 # complete object allocating constructor
//
+ // In addition, C5 is a comdat name with C1 and C2 in it.
switch (T) {
case Ctor_Complete:
Out << "C1";
@@ -3260,8 +3324,8 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
case Ctor_Base:
Out << "C2";
break;
- case Ctor_CompleteAllocating:
- Out << "C3";
+ case Ctor_Comdat:
+ Out << "C5";
break;
}
}
@@ -3271,6 +3335,7 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// ::= D1 # complete object destructor
// ::= D2 # base object destructor
//
+ // In addition, D5 is a comdat name with D1, D2 and, if virtual, D0 in it.
switch (T) {
case Dtor_Deleting:
Out << "D0";
@@ -3281,6 +3346,9 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
case Dtor_Base:
Out << "D2";
break;
+ case Dtor_Comdat:
+ Out << "D5";
+ break;
}
}
@@ -3363,7 +3431,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
// and pointer-to-function expressions are represented as a declaration not
// an expression. We compensate for it here to produce the correct mangling.
ValueDecl *D = A.getAsDecl();
- bool compensateMangling = !A.isDeclForReferenceParam();
+ bool compensateMangling = !A.getParamTypeForDecl()->isReferenceType();
if (compensateMangling) {
Out << 'X';
mangleOperatorName(OO_Amp, 1);
@@ -3674,7 +3742,7 @@ void ItaniumMangleContextImpl::mangleCXXName(const NamedDecl *D,
"Mangling declaration");
CXXNameMangler Mangler(*this, Out, D);
- return Mangler.mangle(D);
+ Mangler.mangle(D);
}
void ItaniumMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
@@ -3691,6 +3759,18 @@ void ItaniumMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
Mangler.mangle(D);
}
+void ItaniumMangleContextImpl::mangleCXXCtorComdat(const CXXConstructorDecl *D,
+ raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out, D, Ctor_Comdat);
+ Mangler.mangle(D);
+}
+
+void ItaniumMangleContextImpl::mangleCXXDtorComdat(const CXXDestructorDecl *D,
+ raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out, D, Dtor_Comdat);
+ Mangler.mangle(D);
+}
+
void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
raw_ostream &Out) {
@@ -3851,3 +3931,4 @@ ItaniumMangleContext *
ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
return new ItaniumMangleContextImpl(Context, Diags);
}
+
diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
index fdc00e3..1a061c4 100644
--- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
@@ -49,10 +49,11 @@ static void mangleFunctionBlock(MangleContext &Context,
void MangleContext::anchor() { }
-enum StdOrFastCC {
- SOF_OTHER,
- SOF_FAST,
- SOF_STD
+enum CCMangling {
+ CCM_Other,
+ CCM_Fast,
+ CCM_Vector,
+ CCM_Std
};
static bool isExternC(const NamedDecl *ND) {
@@ -61,20 +62,22 @@ static bool isExternC(const NamedDecl *ND) {
return cast<VarDecl>(ND)->isExternC();
}
-static StdOrFastCC getStdOrFastCallMangling(const ASTContext &Context,
- const NamedDecl *ND) {
+static CCMangling getCallingConvMangling(const ASTContext &Context,
+ const NamedDecl *ND) {
const TargetInfo &TI = Context.getTargetInfo();
const llvm::Triple &Triple = TI.getTriple();
- if (!Triple.isOSWindows() || Triple.getArch() != llvm::Triple::x86)
- return SOF_OTHER;
+ if (!Triple.isOSWindows() ||
+ !(Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::x86_64))
+ return CCM_Other;
if (Context.getLangOpts().CPlusPlus && !isExternC(ND) &&
TI.getCXXABI() == TargetCXXABI::Microsoft)
- return SOF_OTHER;
+ return CCM_Other;
const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
if (!FD)
- return SOF_OTHER;
+ return CCM_Other;
QualType T = FD->getType();
const FunctionType *FT = T->castAs<FunctionType>();
@@ -82,19 +85,21 @@ static StdOrFastCC getStdOrFastCallMangling(const ASTContext &Context,
CallingConv CC = FT->getCallConv();
switch (CC) {
default:
- return SOF_OTHER;
+ return CCM_Other;
case CC_X86FastCall:
- return SOF_FAST;
+ return CCM_Fast;
case CC_X86StdCall:
- return SOF_STD;
+ return CCM_Std;
+ case CC_X86VectorCall:
+ return CCM_Vector;
}
}
bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
const ASTContext &ASTContext = getASTContext();
- StdOrFastCC CC = getStdOrFastCallMangling(ASTContext, D);
- if (CC != SOF_OTHER)
+ CCMangling CC = getCallingConvMangling(ASTContext, D);
+ if (CC != CCM_Other)
return true;
// In C, functions with no attributes never need to be mangled. Fastpath them.
@@ -131,28 +136,35 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
}
const ASTContext &ASTContext = getASTContext();
- StdOrFastCC CC = getStdOrFastCallMangling(ASTContext, D);
+ CCMangling CC = getCallingConvMangling(ASTContext, D);
bool MCXX = shouldMangleCXXName(D);
const TargetInfo &TI = Context.getTargetInfo();
- if (CC == SOF_OTHER || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
- mangleCXXName(D, Out);
+ if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
+ if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
+ mangleObjCMethodName(OMD, Out);
+ else
+ mangleCXXName(D, Out);
return;
}
Out << '\01';
- if (CC == SOF_STD)
+ if (CC == CCM_Std)
Out << '_';
- else
+ else if (CC == CCM_Fast)
Out << '@';
if (!MCXX)
Out << D->getIdentifier()->getName();
+ else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
+ mangleObjCMethodName(OMD, Out);
else
mangleCXXName(D, Out);
const FunctionDecl *FD = cast<FunctionDecl>(D);
const FunctionType *FT = FD->getType()->castAs<FunctionType>();
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT);
+ if (CC == CCM_Vector)
+ Out << '@';
Out << '@';
if (!Proto) {
Out << '0';
@@ -164,9 +176,11 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
if (!MD->isStatic())
++ArgWords;
for (const auto &AT : Proto->param_types())
- // Size should be aligned to DWORD boundary
- ArgWords += llvm::RoundUpToAlignment(ASTContext.getTypeSize(AT), 32) / 32;
- Out << 4 * ArgWords;
+ // Size should be aligned to pointer size.
+ ArgWords += llvm::RoundUpToAlignment(ASTContext.getTypeSize(AT),
+ TI.getPointerWidth(0)) /
+ TI.getPointerWidth(0);
+ Out << ((TI.getPointerWidth(0) / 8) * ArgWords);
}
void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
@@ -215,16 +229,28 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
mangleObjCMethodName(Method, Stream);
} else {
- const NamedDecl *ND = cast<NamedDecl>(DC);
- if (!shouldMangleDeclName(ND) && ND->getIdentifier())
- Stream << ND->getIdentifier()->getName();
- else {
- // FIXME: We were doing a mangleUnqualifiedName() before, but that's
- // a private member of a class that will soon itself be private to the
- // Itanium C++ ABI object. What should we do now? Right now, I'm just
- // calling the mangleName() method on the MangleContext; is there a
- // better way?
- mangleName(ND, Stream);
+ assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
+ "expected a NamedDecl or BlockDecl");
+ if (isa<BlockDecl>(DC))
+ for (; DC && isa<BlockDecl>(DC); DC = DC->getParent())
+ (void) getBlockId(cast<BlockDecl>(DC), true);
+ assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
+ "expected a TranslationUnitDecl or a NamedDecl");
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
+ mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
+ else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
+ mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
+ else if (auto ND = dyn_cast<NamedDecl>(DC)) {
+ if (!shouldMangleDeclName(ND) && ND->getIdentifier())
+ Stream << ND->getIdentifier()->getName();
+ else {
+ // FIXME: We were doing a mangleUnqualifiedName() before, but that's
+ // a private member of a class that will soon itself be private to the
+ // Itanium C++ ABI object. What should we do now? Right now, I'm just
+ // calling the mangleName() method on the MangleContext; is there a
+ // better way?
+ mangleName(ND, Stream);
+ }
}
}
Stream.flush();
diff --git a/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp b/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp
deleted file mode 100644
index 5f40f03..0000000
--- a/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===--- MangleNumberingContext.cpp - Context for mangling numbers --------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the LambdaMangleContext class, which keeps track of
-// the Itanium C++ ABI mangling numbers for lambda expressions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/MangleNumberingContext.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclCXX.h"
-
-using namespace clang;
-
-unsigned
-MangleNumberingContext::getManglingNumber(const CXXMethodDecl *CallOperator) {
- const FunctionProtoType *Proto
- = CallOperator->getType()->getAs<FunctionProtoType>();
- ASTContext &Context = CallOperator->getASTContext();
-
- QualType Key = Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(),
- FunctionProtoType::ExtProtoInfo());
- Key = Context.getCanonicalType(Key);
- return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
-}
-
-unsigned
-MangleNumberingContext::getManglingNumber(const BlockDecl *BD) {
- // FIXME: Compute a BlockPointerType? Not obvious how.
- const Type *Ty = nullptr;
- return ++ManglingNumbers[Ty];
-}
-
-unsigned
-MangleNumberingContext::getStaticLocalNumber(const VarDecl *VD) {
- // FIXME: Compute a BlockPointerType? Not obvious how.
- const Type *Ty = nullptr;
- return ++ManglingNumbers[Ty];
-}
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
index 6870315..0603d3b 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -28,7 +28,28 @@ namespace {
/// \brief Numbers things which need to correspond across multiple TUs.
/// Typically these are things like static locals, lambdas, or blocks.
class MicrosoftNumberingContext : public MangleNumberingContext {
+ llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
+ unsigned LambdaManglingNumber;
+ unsigned StaticLocalNumber;
+
public:
+ MicrosoftNumberingContext()
+ : MangleNumberingContext(), LambdaManglingNumber(0),
+ StaticLocalNumber(0) {}
+
+ unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
+ return ++LambdaManglingNumber;
+ }
+
+ unsigned getManglingNumber(const BlockDecl *BD) override {
+ const Type *Ty = nullptr;
+ return ++ManglingNumbers[Ty];
+ }
+
+ unsigned getStaticLocalNumber(const VarDecl *VD) override {
+ return ++StaticLocalNumber;
+ }
+
unsigned getManglingNumber(const VarDecl *VD,
unsigned MSLocalManglingNumber) override {
return MSLocalManglingNumber;
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
index e6a6d09..72f90f6 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
@@ -27,7 +27,6 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/Support/MathExtras.h"
using namespace clang;
@@ -161,7 +160,7 @@ public:
unsigned &discriminator = Uniquifier[ND];
if (!discriminator)
discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())];
- disc = discriminator;
+ disc = discriminator + 1;
return true;
}
@@ -191,8 +190,8 @@ class MicrosoftCXXNameMangler {
const NamedDecl *Structor;
unsigned StructorType;
- typedef llvm::StringMap<unsigned> BackRefMap;
- BackRefMap NameBackReferences;
+ typedef llvm::SmallVector<std::string, 10> BackRefVec;
+ BackRefVec NameBackReferences;
typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap;
ArgBackRefMap TypeBackReferences;
@@ -234,7 +233,7 @@ public:
QualifierMangleMode QMM = QMM_Mangle);
void mangleFunctionType(const FunctionType *T,
const FunctionDecl *D = nullptr,
- bool ForceInstMethod = false);
+ bool ForceThisQuals = false);
void mangleNestedName(const NamedDecl *ND);
private:
@@ -279,7 +278,8 @@ private:
void mangleTemplateArgs(const TemplateDecl *TD,
const TemplateArgumentList &TemplateArgs);
- void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA);
+ void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA,
+ const NamedDecl *Parm);
};
}
@@ -338,9 +338,7 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
bool
MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) {
- return SL->isAscii() || SL->isWide();
- // TODO: This needs to be updated when MSVC gains support for Unicode
- // literals.
+ return true;
}
void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
@@ -441,7 +439,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
mangleQualifiers(Ty.getQualifiers(), false);
} else {
mangleType(Ty, SR, QMM_Drop);
- mangleQualifiers(Ty.getLocalQualifiers(), false);
+ mangleQualifiers(Ty.getQualifiers(), false);
}
}
@@ -801,10 +799,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
// <postfix> ::= <unqualified-name> [<postfix>]
// ::= <substitution> [<postfix>]
- if (isLambda(ND))
- return;
-
- const DeclContext *DC = ND->getDeclContext();
+ const DeclContext *DC = getEffectiveDeclContext(ND);
while (!DC->isTranslationUnit()) {
if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) {
@@ -856,6 +851,8 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// <operator-name> ::= ?_E # vector deleting destructor
// FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need
// it.
+ case Dtor_Comdat:
+ llvm_unreachable("not expecting a COMDAT");
}
llvm_unreachable("Unsupported dtor type?");
}
@@ -994,22 +991,14 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) {
// <source name> ::= <identifier> @
- BackRefMap::iterator Found;
- if (NameBackReferences.size() < 10) {
- size_t Size = NameBackReferences.size();
- bool Inserted;
- std::tie(Found, Inserted) =
- NameBackReferences.insert(std::make_pair(Name, Size));
- if (Inserted)
- Found = NameBackReferences.end();
- } else {
- Found = NameBackReferences.find(Name);
- }
-
+ BackRefVec::iterator Found =
+ std::find(NameBackReferences.begin(), NameBackReferences.end(), Name);
if (Found == NameBackReferences.end()) {
+ if (NameBackReferences.size() < 10)
+ NameBackReferences.push_back(Name);
Out << Name << '@';
} else {
- Out << Found->second;
+ Out << (Found - NameBackReferences.begin());
}
}
@@ -1025,7 +1014,7 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
// Templates have their own context for back references.
ArgBackRefMap OuterArgsContext;
- BackRefMap OuterTemplateContext;
+ BackRefVec OuterTemplateContext;
NameBackReferences.swap(OuterTemplateContext);
TypeBackReferences.swap(OuterArgsContext);
@@ -1051,8 +1040,10 @@ void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
// Make sure booleans are encoded as 0/1.
if (IsBoolean && Value.getBoolValue())
mangleNumber(1);
- else
+ else if (Value.isSigned())
mangleNumber(Value.getSExtValue());
+ else
+ mangleNumber(Value.getZExtValue());
}
void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
@@ -1104,12 +1095,18 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
void MicrosoftCXXNameMangler::mangleTemplateArgs(
const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) {
// <template-args> ::= <template-arg>+
+ const TemplateParameterList *TPL = TD->getTemplateParameters();
+ assert(TPL->size() == TemplateArgs.size() &&
+ "size mismatch between args and parms!");
+
+ unsigned Idx = 0;
for (const TemplateArgument &TA : TemplateArgs.asArray())
- mangleTemplateArg(TD, TA);
+ mangleTemplateArg(TD, TA, TPL->getParam(Idx++));
}
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
- const TemplateArgument &TA) {
+ const TemplateArgument &TA,
+ const NamedDecl *Parm) {
// <template-arg> ::= <type>
// ::= <integer-literal>
// ::= <member-data-pointer>
@@ -1142,7 +1139,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
else
mangle(FD, "$1?");
} else {
- mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?");
+ mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?");
}
break;
}
@@ -1172,18 +1169,33 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
case TemplateArgument::Pack: {
ArrayRef<TemplateArgument> TemplateArgs = TA.getPackAsArray();
if (TemplateArgs.empty()) {
- Out << "$S";
+ if (isa<TemplateTypeParmDecl>(Parm) ||
+ isa<TemplateTemplateParmDecl>(Parm))
+ Out << "$$V";
+ else if (isa<NonTypeTemplateParmDecl>(Parm))
+ Out << "$S";
+ else
+ llvm_unreachable("unexpected template parameter decl!");
} else {
for (const TemplateArgument &PA : TemplateArgs)
- mangleTemplateArg(TD, PA);
+ mangleTemplateArg(TD, PA, Parm);
}
break;
}
- case TemplateArgument::Template:
- mangleType(cast<TagDecl>(
- TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl()));
+ case TemplateArgument::Template: {
+ const NamedDecl *ND =
+ TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl();
+ if (const auto *TD = dyn_cast<TagDecl>(ND)) {
+ mangleType(TD);
+ } else if (isa<TypeAliasDecl>(ND)) {
+ Out << "$$Y";
+ mangleName(ND);
+ } else {
+ llvm_unreachable("unexpected template template NamedDecl!");
+ }
break;
}
+ }
}
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
@@ -1473,6 +1485,8 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
case BuiltinType::Int128: Out << "_L"; break;
case BuiltinType::UInt128: Out << "_M"; break;
case BuiltinType::Bool: Out << "_N"; break;
+ case BuiltinType::Char16: Out << "_S"; break;
+ case BuiltinType::Char32: Out << "_U"; break;
case BuiltinType::WChar_S:
case BuiltinType::WChar_U: Out << "_W"; break;
@@ -1498,8 +1512,6 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
case BuiltinType::NullPtr: Out << "$$T"; break;
- case BuiltinType::Char16:
- case BuiltinType::Char32:
case BuiltinType::Half: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
@@ -1518,8 +1530,13 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
// Structors only appear in decls, so at this point we know it's not a
// structor type.
// FIXME: This may not be lambda-friendly.
- Out << "$$A6";
- mangleFunctionType(T);
+ if (T->getTypeQuals() || T->getRefQualifier() != RQ_None) {
+ Out << "$$A8@@";
+ mangleFunctionType(T, /*D=*/nullptr, /*ForceThisQuals=*/true);
+ } else {
+ Out << "$$A6";
+ mangleFunctionType(T);
+ }
}
void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
SourceRange) {
@@ -1528,7 +1545,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
const FunctionDecl *D,
- bool ForceInstMethod) {
+ bool ForceThisQuals) {
// <function-type> ::= <this-cvr-qualifiers> <calling-convention>
// <return-type> <argument-list> <throw-spec>
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
@@ -1536,21 +1553,21 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
SourceRange Range;
if (D) Range = D->getSourceRange();
- bool IsStructor = false, IsInstMethod = ForceInstMethod;
+ bool IsStructor = false, HasThisQuals = ForceThisQuals;
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) {
if (MD->isInstance())
- IsInstMethod = true;
+ HasThisQuals = true;
if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
IsStructor = true;
}
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
- if (IsInstMethod) {
+ if (HasThisQuals) {
Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals());
- manglePointerExtQualifiers(Quals, nullptr);
+ manglePointerExtQualifiers(Quals, /*PointeeType=*/nullptr);
mangleRefQualifier(Proto->getRefQualifier());
- mangleQualifiers(Quals, false);
+ mangleQualifiers(Quals, /*IsMember=*/false);
}
mangleCallingConvention(T);
@@ -1670,6 +1687,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
// ::= H # __export __stdcall
// ::= I # __fastcall
// ::= J # __export __fastcall
+ // ::= Q # __vectorcall
// The 'export' calling conventions are from a bygone era
// (*cough*Win16*cough*) when functions were declared for export with
// that keyword. (It didn't actually export them, it just made them so
@@ -1686,6 +1704,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
case CC_X86ThisCall: Out << 'E'; break;
case CC_X86StdCall: Out << 'G'; break;
case CC_X86FastCall: Out << 'I'; break;
+ case CC_X86VectorCall: Out << 'Q'; break;
}
}
void MicrosoftCXXNameMangler::mangleThrowSpecification(
@@ -2331,7 +2350,7 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD,
raw_ostream &Out) {
- // TODO: This is not correct, especially with respect to MSVC2013. MSVC2013
+ // TODO: This is not correct, especially with respect to VS "14". VS "14"
// utilizes thread local variables to implement thread safe, re-entrant
// initialization for statics. They no longer differentiate between an
// externally visible and non-externally visible static with respect to
@@ -2420,14 +2439,10 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
Mangler.getStream() << "\01??_C@_";
// <char-type>: The "kind" of string literal is encoded into the mangled name.
- // TODO: This needs to be updated when MSVC gains support for unicode
- // literals.
- if (SL->isAscii())
- Mangler.getStream() << '0';
- else if (SL->isWide())
+ if (SL->isWide())
Mangler.getStream() << '1';
else
- llvm_unreachable("unexpected string literal kind!");
+ Mangler.getStream() << '0';
// <literal-length>: The next part of the mangled name consists of the length
// of the string.
@@ -2506,42 +2521,16 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
} else if (isLetter(Byte & 0x7f)) {
Mangler.getStream() << '?' << static_cast<char>(Byte & 0x7f);
} else {
- switch (Byte) {
- case ',':
- Mangler.getStream() << "?0";
- break;
- case '/':
- Mangler.getStream() << "?1";
- break;
- case '\\':
- Mangler.getStream() << "?2";
- break;
- case ':':
- Mangler.getStream() << "?3";
- break;
- case '.':
- Mangler.getStream() << "?4";
- break;
- case ' ':
- Mangler.getStream() << "?5";
- break;
- case '\n':
- Mangler.getStream() << "?6";
- break;
- case '\t':
- Mangler.getStream() << "?7";
- break;
- case '\'':
- Mangler.getStream() << "?8";
- break;
- case '-':
- Mangler.getStream() << "?9";
- break;
- default:
- Mangler.getStream() << "?$";
- Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf));
- Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf));
- break;
+ const char SpecialChars[] = {',', '/', '\\', ':', '.',
+ ' ', '\n', '\t', '\'', '-'};
+ const char *Pos =
+ std::find(std::begin(SpecialChars), std::end(SpecialChars), Byte);
+ if (Pos != std::end(SpecialChars)) {
+ Mangler.getStream() << '?' << (Pos - std::begin(SpecialChars));
+ } else {
+ Mangler.getStream() << "?$";
+ Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf));
+ Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf));
}
}
};
@@ -2550,7 +2539,10 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
unsigned NumCharsToMangle = std::min(32U, SL->getLength());
for (unsigned I = 0, E = NumCharsToMangle * SL->getCharByteWidth(); I != E;
++I)
- MangleByte(GetBigEndianByte(I));
+ if (SL->isWide())
+ MangleByte(GetBigEndianByte(I));
+ else
+ MangleByte(GetLittleEndianByte(I));
// Encode the NUL terminator if there is room.
if (NumCharsToMangle < 32)
diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
index 986b3b5..3dc750a 100644
--- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
@@ -10,6 +10,7 @@
#include "clang/AST/NSAPI.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -46,6 +47,10 @@ Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
Sel = Ctx.Selectors.getUnarySelector(
&Ctx.Idents.get("stringWithUTF8String"));
break;
+ case NSStr_initWithUTF8String:
+ Sel = Ctx.Selectors.getUnarySelector(
+ &Ctx.Idents.get("initWithUTF8String"));
+ break;
case NSStr_stringWithCStringEncoding: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("stringWithCString"),
@@ -379,6 +384,32 @@ bool NSAPI::isObjCNSUIntegerType(QualType T) const {
return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
}
+StringRef NSAPI::GetNSIntegralKind(QualType T) const {
+ if (!Ctx.getLangOpts().ObjC1 || T.isNull())
+ return StringRef();
+
+ while (const TypedefType *TDT = T->getAs<TypedefType>()) {
+ StringRef NSIntegralResust =
+ llvm::StringSwitch<StringRef>(
+ TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
+ .Case("int8_t", "int8_t")
+ .Case("int16_t", "int16_t")
+ .Case("int32_t", "int32_t")
+ .Case("NSInteger", "NSInteger")
+ .Case("int64_t", "int64_t")
+ .Case("uint8_t", "uint8_t")
+ .Case("uint16_t", "uint16_t")
+ .Case("uint32_t", "uint32_t")
+ .Case("NSUInteger", "NSUInteger")
+ .Case("uint64_t", "uint64_t")
+ .Default(StringRef());
+ if (!NSIntegralResust.empty())
+ return NSIntegralResust;
+ T = TDT->desugar();
+ }
+ return StringRef();
+}
+
bool NSAPI::isObjCTypedef(QualType T,
StringRef name, IdentifierInfo *&II) const {
if (!Ctx.getLangOpts().ObjC1)
diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
index 1f041aa..50a0050 100644
--- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
@@ -66,7 +66,7 @@ NestedNameSpecifier::Create(const ASTContext &Context,
"Broken nested name specifier");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredNamespaceOrAlias);
+ Mockup.Prefix.setInt(StoredDecl);
Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
return FindOrInsert(Context, Mockup);
}
@@ -82,7 +82,7 @@ NestedNameSpecifier::Create(const ASTContext &Context,
"Broken nested name specifier");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredNamespaceOrAlias);
+ Mockup.Prefix.setInt(StoredDecl);
Mockup.Specifier = Alias;
return FindOrInsert(Context, Mockup);
}
@@ -118,6 +118,16 @@ NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
return Context.GlobalNestedNameSpecifier;
}
+NestedNameSpecifier *
+NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
+ CXXRecordDecl *RD) {
+ NestedNameSpecifier Mockup;
+ Mockup.Prefix.setPointer(nullptr);
+ Mockup.Prefix.setInt(StoredDecl);
+ Mockup.Specifier = RD;
+ return FindOrInsert(Context, Mockup);
+}
+
NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
if (!Specifier)
return Global;
@@ -126,9 +136,12 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
case StoredIdentifier:
return Identifier;
- case StoredNamespaceOrAlias:
- return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace
- : NamespaceAlias;
+ case StoredDecl: {
+ NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
+ if (isa<CXXRecordDecl>(ND))
+ return Super;
+ return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
+ }
case StoredTypeSpec:
return TypeSpec;
@@ -140,24 +153,29 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
llvm_unreachable("Invalid NNS Kind!");
}
-/// \brief Retrieve the namespace stored in this nested name
-/// specifier.
+/// \brief Retrieve the namespace stored in this nested name specifier.
NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
- if (Prefix.getInt() == StoredNamespaceOrAlias)
+ if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
return nullptr;
}
-/// \brief Retrieve the namespace alias stored in this nested name
-/// specifier.
+/// \brief Retrieve the namespace alias stored in this nested name specifier.
NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
- if (Prefix.getInt() == StoredNamespaceOrAlias)
+ if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
return nullptr;
}
+/// \brief Retrieve the record declaration stored in this nested name specifier.
+CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
+ if (Prefix.getInt() == StoredDecl)
+ return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
+
+ return nullptr;
+}
/// \brief Whether this nested name specifier refers to a dependent
/// type or not.
@@ -172,6 +190,15 @@ bool NestedNameSpecifier::isDependent() const {
case Global:
return false;
+ case Super: {
+ CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
+ for (const auto &Base : RD->bases())
+ if (Base.getType()->isDependentType())
+ return true;
+
+ return false;
+ }
+
case TypeSpec:
case TypeSpecWithTemplate:
return getAsType()->isDependentType();
@@ -191,8 +218,9 @@ bool NestedNameSpecifier::isInstantiationDependent() const {
case Namespace:
case NamespaceAlias:
case Global:
+ case Super:
return false;
-
+
case TypeSpec:
case TypeSpecWithTemplate:
return getAsType()->isInstantiationDependentType();
@@ -209,6 +237,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
case Namespace:
case NamespaceAlias:
case Global:
+ case Super:
return false;
case TypeSpec:
@@ -246,6 +275,10 @@ NestedNameSpecifier::print(raw_ostream &OS,
case Global:
break;
+ case Super:
+ OS << "__super";
+ break;
+
case TypeSpecWithTemplate:
OS << "template ";
// Fall through to print the type.
@@ -304,6 +337,7 @@ NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Super:
// The location of the identifier or namespace name.
Length += sizeof(unsigned);
break;
@@ -369,6 +403,7 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Super:
return SourceRange(LoadSourceLocation(Data, Offset),
LoadSourceLocation(Data, Offset + sizeof(unsigned)));
@@ -552,6 +587,17 @@ void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
+void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
+ CXXRecordDecl *RD,
+ SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc) {
+ Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+}
+
void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
NestedNameSpecifier *Qualifier,
SourceRange R) {
@@ -583,6 +629,7 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
}
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
break;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
index b3deeba..0d070a4 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -636,23 +636,12 @@ protected:
HasOwnVFPtr(false),
FirstNearlyEmptyVBase(nullptr) {}
- /// Reset this RecordLayoutBuilder to a fresh state, using the given
- /// alignment as the initial alignment. This is used for the
- /// correct layout of vb-table pointers in MSVC.
- void resetWithTargetAlignment(CharUnits TargetAlignment) {
- const ASTContext &Context = this->Context;
- EmptySubobjectMap *EmptySubobjects = this->EmptySubobjects;
- this->~RecordLayoutBuilder();
- new (this) RecordLayoutBuilder(Context, EmptySubobjects);
- Alignment = UnpackedAlignment = TargetAlignment;
- }
-
void Layout(const RecordDecl *D);
void Layout(const CXXRecordDecl *D);
void Layout(const ObjCInterfaceDecl *D);
void LayoutFields(const RecordDecl *D);
- void LayoutField(const FieldDecl *D);
+ void LayoutField(const FieldDecl *D, bool InsertExtraPadding);
void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize,
bool FieldPacked, const FieldDecl *D);
void LayoutBitField(const FieldDecl *D);
@@ -1104,7 +1093,7 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
// Only lay out the virtual base if it's not an indirect primary base.
if (!IndirectPrimaryBase) {
// Only visit virtual bases once.
- if (!VisitedVirtualBases.insert(BaseDecl))
+ if (!VisitedVirtualBases.insert(BaseDecl).second)
continue;
const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
@@ -1331,7 +1320,7 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
// Layout each ivar sequentially.
for (const ObjCIvarDecl *IVD = D->all_declared_ivar_begin(); IVD;
IVD = IVD->getNextIvar())
- LayoutField(IVD);
+ LayoutField(IVD, false);
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
@@ -1341,8 +1330,22 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
// Layout each field, for now, just sequentially, respecting alignment. In
// the future, this will need to be tweakable by targets.
- for (const auto *Field : D->fields())
- LayoutField(Field);
+ bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true);
+ bool HasFlexibleArrayMember = D->hasFlexibleArrayMember();
+ for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) {
+ auto Next(I);
+ ++Next;
+ LayoutField(*I,
+ InsertExtraPadding && (Next != End || !HasFlexibleArrayMember));
+ }
+}
+
+// Rounds the specified size to have it a multiple of the char size.
+static uint64_t
+roundUpSizeToCharAlignment(uint64_t Size,
+ const ASTContext &Context) {
+ uint64_t CharAlignment = Context.getTargetInfo().getCharAlign();
+ return llvm::RoundUpToAlignment(Size, CharAlignment);
}
void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
@@ -1382,7 +1385,9 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
if (IsUnion) {
- setDataSize(std::max(getDataSizeInBits(), FieldSize));
+ uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize,
+ Context);
+ setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
FieldOffset = 0;
} else {
// The bitfield is allocated starting at the next offset aligned
@@ -1413,9 +1418,9 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
uint64_t FieldSize = D->getBitWidthValue(Context);
- std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType());
- uint64_t TypeSize = FieldInfo.first;
- unsigned FieldAlign = FieldInfo.second;
+ TypeInfo FieldInfo = Context.getTypeInfo(D->getType());
+ uint64_t TypeSize = FieldInfo.Width;
+ unsigned FieldAlign = FieldInfo.Align;
// UnfilledBitsInLastUnit is the difference between the end of the
// last allocated bitfield (i.e. the first bit offset available for
@@ -1607,9 +1612,9 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// For unions, this is just a max operation, as usual.
if (IsUnion) {
- // FIXME: I think FieldSize should be TypeSize here.
- setDataSize(std::max(getDataSizeInBits(), FieldSize));
-
+ uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize,
+ Context);
+ setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
// For non-zero-width bitfields in ms_struct structs, allocate a new
// storage unit if necessary.
} else if (IsMsStruct && FieldSize) {
@@ -1645,7 +1650,8 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
Context.toCharUnitsFromBits(UnpackedFieldAlign));
}
-void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
+void RecordLayoutBuilder::LayoutField(const FieldDecl *D,
+ bool InsertExtraPadding) {
if (D->isBitField()) {
LayoutBitField(D);
return;
@@ -1749,6 +1755,15 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
Context.toBits(UnpackedFieldOffset),
Context.toBits(UnpackedFieldAlign), FieldPacked, D);
+ if (InsertExtraPadding) {
+ CharUnits ASanAlignment = CharUnits::fromQuantity(8);
+ CharUnits ExtraSizeForAsan = ASanAlignment;
+ if (FieldSize % ASanAlignment)
+ ExtraSizeForAsan +=
+ ASanAlignment - CharUnits::fromQuantity(FieldSize % ASanAlignment);
+ FieldSize += ExtraSizeForAsan;
+ }
+
// Reserve space for this field.
uint64_t FieldSizeInBits = Context.toBits(FieldSize);
if (IsUnion)
@@ -2097,7 +2112,7 @@ static bool isMsLayout(const RecordDecl* D) {
// * There is a distinction between alignment and required alignment.
// __declspec(align) changes the required alignment of a struct. This
// alignment is _always_ obeyed, even in the presence of #pragma pack. A
-// record inherites required alignment from all of its fields an bases.
+// record inherits required alignment from all of its fields and bases.
// * __declspec(align) on bitfields has the effect of changing the bitfield's
// alignment instead of its required alignment. This is the only known way
// to make the alignment of a struct bigger than 8. Interestingly enough
@@ -2181,8 +2196,9 @@ public:
FieldOffsets.push_back(FieldOffset);
}
/// \brief Compute the set of virtual bases for which vtordisps are required.
- llvm::SmallPtrSet<const CXXRecordDecl *, 2>
- computeVtorDispSet(const CXXRecordDecl *RD);
+ void computeVtorDispSet(
+ llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
+ const CXXRecordDecl *RD) const;
const ASTContext &Context;
/// \brief The size of the record being laid out.
CharUnits Size;
@@ -2203,6 +2219,8 @@ public:
CharUnits CurrentBitfieldSize;
/// \brief Offset to the virtual base table pointer (if one exists).
CharUnits VBPtrOffset;
+ /// \brief Minimum record size possible.
+ CharUnits MinEmptyStructSize;
/// \brief The size and alignment info of a pointer.
ElementInfo PointerInfo;
/// \brief The primary base class (if one exists).
@@ -2260,12 +2278,18 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
MicrosoftRecordLayoutBuilder::ElementInfo
MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
const FieldDecl *FD) {
+ // Get the alignment of the field type's natural alignment, ignore any
+ // alignment attributes.
ElementInfo Info;
std::tie(Info.Size, Info.Alignment) =
- Context.getTypeInfoInChars(FD->getType());
- // Respect align attributes.
- CharUnits FieldRequiredAlignment =
+ Context.getTypeInfoInChars(FD->getType()->getUnqualifiedDesugaredType());
+ // Respect align attributes on the field.
+ CharUnits FieldRequiredAlignment =
Context.toCharUnitsFromBits(FD->getMaxAlignment());
+ // Respect align attributes on the type.
+ if (Context.isAlignmentRequired(FD->getType()))
+ FieldRequiredAlignment = std::max(
+ Context.getTypeAlignInChars(FD->getType()), FieldRequiredAlignment);
// Respect attributes applied to subobjects of the field.
if (FD->isBitField())
// For some reason __declspec align impacts alignment rather than required
@@ -2292,6 +2316,8 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
}
void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
+ // For C record layout, zero-sized records always have size 4.
+ MinEmptyStructSize = CharUnits::fromQuantity(4);
initializeLayout(RD);
layoutFields(RD);
DataSize = Size = Size.RoundUpToAlignment(Alignment);
@@ -2301,6 +2327,8 @@ void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
}
void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
+ // The C++ standard says that empty structs have size 1.
+ MinEmptyStructSize = CharUnits::One();
initializeLayout(RD);
initializeCXXLayout(RD);
layoutNonVirtualBases(RD);
@@ -2599,14 +2627,14 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
}
VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
// Compute the vtordisp set.
- llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet =
- computeVtorDispSet(RD);
+ llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
+ computeVtorDispSet(HasVtorDispSet, RD);
// Iterate through the virtual bases and lay them out.
const ASTRecordLayout *PreviousBaseLayout = nullptr;
for (const CXXBaseSpecifier &VBase : RD->vbases()) {
const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
- bool HasVtordisp = HasVtordispSet.count(BaseDecl);
+ bool HasVtordisp = HasVtorDispSet.count(BaseDecl) > 0;
// Insert padding between two bases if the left first one is zero sized or
// contains a zero sized subobject and the right is zero sized or one leads
// with a zero sized base. The padding between virtual bases is 4
@@ -2629,7 +2657,7 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
// Respect required alignment. Note that in 32-bit mode Required alignment
- // may be 0 nad cause size not to be updated.
+ // may be 0 and cause size not to be updated.
DataSize = Size;
if (!RequiredAlignment.isZero()) {
Alignment = std::max(Alignment, RequiredAlignment);
@@ -2639,11 +2667,15 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
Size = Size.RoundUpToAlignment(RoundingAlignment);
}
- // Zero-sized structures have size equal to their alignment.
if (Size.isZero()) {
EndsWithZeroSizedObject = true;
LeadsWithZeroSizedBase = true;
- Size = Alignment;
+ // Zero-sized structures have size equal to their alignment if a
+ // __declspec(align) came into play.
+ if (RequiredAlignment >= MinEmptyStructSize)
+ Size = Alignment;
+ else
+ Size = MinEmptyStructSize;
}
}
@@ -2665,10 +2697,9 @@ RequiresVtordisp(const llvm::SmallPtrSetImpl<const CXXRecordDecl *> &
return false;
}
-llvm::SmallPtrSet<const CXXRecordDecl *, 2>
-MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) {
- llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet;
-
+void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
+ llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
+ const CXXRecordDecl *RD) const {
// /vd2 or #pragma vtordisp(2): Always use vtordisps for virtual bases with
// vftables.
if (RD->getMSVtorDispMode() == MSVtorDispAttr::ForVFTable) {
@@ -2678,7 +2709,7 @@ MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) {
if (Layout.hasExtendableVFPtr())
HasVtordispSet.insert(BaseDecl);
}
- return HasVtordispSet;
+ return;
}
// If any of our bases need a vtordisp for this type, so do we. Check our
@@ -2695,7 +2726,7 @@ MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) {
// * #pragma vtordisp(0) or the /vd0 flag are in use.
if ((!RD->hasUserDeclaredConstructor() && !RD->hasUserDeclaredDestructor()) ||
RD->getMSVtorDispMode() == MSVtorDispAttr::Never)
- return HasVtordispSet;
+ return;
// /vd1 or #pragma vtordisp(1): Try to guess based on whether we think it's
// possible for a partially constructed object with virtual base overrides to
// escape a non-trivial constructor.
@@ -2706,9 +2737,9 @@ MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) {
// vtordisp.
llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
- // Seed the working set with our non-destructor virtual methods.
+ // Seed the working set with our non-destructor, non-pure virtual methods.
for (const CXXMethodDecl *MD : RD->methods())
- if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD))
+ if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure())
Work.insert(MD);
while (!Work.empty()) {
const CXXMethodDecl *MD = *Work.begin();
@@ -2730,7 +2761,6 @@ MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) {
RequiresVtordisp(BasesWithOverriddenMethods, BaseDecl))
HasVtordispSet.insert(BaseDecl);
}
- return HasVtordispSet;
}
/// \brief Get or compute information about the layout of the specified record
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
index a8483dc..68c7e72 100644
--- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -104,6 +104,26 @@ Stmt *Stmt::IgnoreImplicit() {
return s;
}
+/// \brief Skip no-op (attributed, compound) container stmts and skip captured
+/// stmt at the top, if \a IgnoreCaptured is true.
+Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) {
+ Stmt *S = this;
+ if (IgnoreCaptured)
+ if (auto CapS = dyn_cast_or_null<CapturedStmt>(S))
+ S = CapS->getCapturedStmt();
+ while (true) {
+ if (auto AS = dyn_cast_or_null<AttributedStmt>(S))
+ S = AS->getSubStmt();
+ else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) {
+ if (CS->size() != 1)
+ break;
+ S = CS->body_back();
+ } else
+ break;
+ }
+ return S;
+}
+
/// \brief Strip off all label-like statements.
///
/// This will strip off label statements, case statements, attributed
@@ -254,7 +274,7 @@ SourceLocation Stmt::getLocEnd() const {
CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts,
SourceLocation LB, SourceLocation RB)
- : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) {
+ : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) {
CompoundStmtBits.NumStmts = Stmts.size();
assert(CompoundStmtBits.NumStmts == Stmts.size() &&
"NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
@@ -357,6 +377,11 @@ unsigned AsmStmt::getNumPlusOperands() const {
return Res;
}
+char GCCAsmStmt::AsmStringPiece::getModifier() const {
+ assert(isOperand() && "Only Operands can have modifiers.");
+ return isLetter(Str[0]) ? Str[0] : '\0';
+}
+
StringRef GCCAsmStmt::getClobber(unsigned i) const {
return getClobberStringLiteral(i)->getString();
}
@@ -517,17 +542,25 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
CurStringPiece.clear();
}
- // Handle %x4 and %x[foo] by capturing x as the modifier character.
- char Modifier = '\0';
+ // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that
+ // don't (e.g., %x4). 'x' following the '%' is the constraint modifier.
+
+ const char *Begin = CurPtr - 1; // Points to the character following '%'.
+ const char *Percent = Begin - 1; // Points to '%'.
+
if (isLetter(EscapedChar)) {
if (CurPtr == StrEnd) { // Premature end.
DiagOffs = CurPtr-StrStart-1;
return diag::err_asm_invalid_escape;
}
- Modifier = EscapedChar;
EscapedChar = *CurPtr++;
}
+ const TargetInfo &TI = C.getTargetInfo();
+ const SourceManager &SM = C.getSourceManager();
+ const LangOptions &LO = C.getLangOpts();
+
+ // Handle operands that don't have asmSymbolicName (e.g., %x4).
if (isDigit(EscapedChar)) {
// %n - Assembler operand n
unsigned N = 0;
@@ -543,11 +576,21 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
return diag::err_asm_invalid_operand_number;
}
- Pieces.push_back(AsmStringPiece(N, Modifier));
+ // Str contains "x4" (Operand without the leading %).
+ std::string Str(Begin, CurPtr - Begin);
+
+ // (BeginLoc, EndLoc) represents the range of the operand we are currently
+ // processing. Unlike Str, the range includes the leading '%'.
+ SourceLocation BeginLoc =
+ getAsmString()->getLocationOfByte(Percent - StrStart, SM, LO, TI);
+ SourceLocation EndLoc =
+ getAsmString()->getLocationOfByte(CurPtr - StrStart, SM, LO, TI);
+
+ Pieces.push_back(AsmStringPiece(N, Str, BeginLoc, EndLoc));
continue;
}
- // Handle %[foo], a symbolic operand reference.
+ // Handle operands that have asmSymbolicName (e.g., %x[foo]).
if (EscapedChar == '[') {
DiagOffs = CurPtr-StrStart-1;
@@ -566,7 +609,18 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
DiagOffs = CurPtr-StrStart;
return diag::err_asm_unknown_symbolic_operand_name;
}
- Pieces.push_back(AsmStringPiece(N, Modifier));
+
+ // Str contains "x[foo]" (Operand without the leading %).
+ std::string Str(Begin, NameEnd + 1 - Begin);
+
+ // (BeginLoc, EndLoc) represents the range of the operand we are currently
+ // processing. Unlike Str, the range includes the leading '%'.
+ SourceLocation BeginLoc =
+ getAsmString()->getLocationOfByte(Percent - StrStart, SM, LO, TI);
+ SourceLocation EndLoc =
+ getAsmString()->getLocationOfByte(NameEnd + 1 - StrStart, SM, LO, TI);
+
+ Pieces.push_back(AsmStringPiece(N, Str, BeginLoc, EndLoc));
CurPtr = NameEnd+1;
continue;
@@ -956,20 +1010,22 @@ Expr* ReturnStmt::getRetValue() {
return cast_or_null<Expr>(RetExpr);
}
-SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,
- Stmt *Handler, int HandlerIndex, int HandlerParentIndex)
- : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc),
- HandlerIndex(HandlerIndex), HandlerParentIndex(HandlerParentIndex) {
- Children[TRY] = TryBlock;
+SEHTryStmt::SEHTryStmt(bool IsCXXTry,
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler)
+ : Stmt(SEHTryStmtClass),
+ IsCXXTry(IsCXXTry),
+ TryLoc(TryLoc)
+{
+ Children[TRY] = TryBlock;
Children[HANDLER] = Handler;
}
-SEHTryStmt *SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry,
+SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry,
SourceLocation TryLoc, Stmt *TryBlock,
- Stmt *Handler, int HandlerIndex,
- int HandlerParentIndex) {
- return new (C) SEHTryStmt(IsCXXTry, TryLoc, TryBlock, Handler, HandlerIndex,
- HandlerParentIndex);
+ Stmt *Handler) {
+ return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler);
}
SEHExceptStmt* SEHTryStmt::getExceptHandler() const {
@@ -1120,17 +1176,24 @@ StmtRange OMPClause::children() {
llvm_unreachable("unknown OMPClause");
}
-OMPPrivateClause *OMPPrivateClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), varlist_end());
+}
+
+OMPPrivateClause *
+OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL) {
+ // Allocate space for private variables and initializer expressions.
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
- OMPPrivateClause *Clause = new (Mem) OMPPrivateClause(StartLoc, LParenLoc,
- EndLoc, VL.size());
+ 2 * sizeof(Expr *) * VL.size());
+ OMPPrivateClause *Clause =
+ new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setPrivateCopies(PrivateVL);
return Clause;
}
@@ -1138,23 +1201,35 @@ OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 2 * sizeof(Expr *) * N);
return new (Mem) OMPPrivateClause(N);
}
-OMPFirstprivateClause *OMPFirstprivateClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
+void OMPFirstprivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), varlist_end());
+}
+
+void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of inits is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), getPrivateCopies().end());
+}
+
+OMPFirstprivateClause *
+OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL,
+ ArrayRef<Expr *> InitVL) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
- OMPFirstprivateClause *Clause = new (Mem) OMPFirstprivateClause(StartLoc,
- LParenLoc,
- EndLoc,
- VL.size());
+ 3 * sizeof(Expr *) * VL.size());
+ OMPFirstprivateClause *Clause =
+ new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
+ Clause->setPrivateCopies(PrivateVL);
+ Clause->setInits(InitVL);
return Clause;
}
@@ -1162,7 +1237,7 @@ OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause),
llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
+ 3 * sizeof(Expr *) * N);
return new (Mem) OMPFirstprivateClause(N);
}
@@ -1306,6 +1381,24 @@ void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
std::copy(Clauses.begin(), Clauses.end(), getClauses().begin());
}
+void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of loop counters is not the same as the collapsed number");
+ std::copy(A.begin(), A.end(), getCounters().begin());
+}
+
+void OMPLoopDirective::setUpdates(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of counter updates is not the same as the collapsed number");
+ std::copy(A.begin(), A.end(), getUpdates().begin());
+}
+
+void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of counter finals is not the same as the collapsed number");
+ std::copy(A.begin(), A.end(), getFinals().begin());
+}
+
OMPReductionClause *OMPReductionClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
@@ -1348,6 +1441,21 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
return new (Mem) OMPFlushClause(N);
}
+const OMPClause *
+OMPExecutableDirective::getSingleClause(OpenMPClauseKind K) const {
+ auto ClauseFilter =
+ [=](const OMPClause *C) -> bool { return C->getClauseKind() == K; };
+ OMPExecutableDirective::filtered_clause_iterator<decltype(ClauseFilter)> I(
+ clauses(), ClauseFilter);
+
+ if (I) {
+ auto *Clause = *I;
+ assert(!++I && "There are at least 2 clauses of the specified kind");
+ return Clause;
+ }
+ return nullptr;
+}
+
OMPParallelDirective *OMPParallelDirective::Create(
const ASTContext &C,
SourceLocation StartLoc,
@@ -1378,15 +1486,27 @@ OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C,
OMPSimdDirective *
OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective),
llvm::alignOf<OMPClause *>());
void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
OMPSimdDirective *Dir = new (Mem)
OMPSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
return Dir;
}
@@ -1397,22 +1517,42 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C,
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective),
llvm::alignOf<OMPClause *>());
void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses);
}
OMPForDirective *
OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective),
llvm::alignOf<OMPClause *>());
void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
OMPForDirective *Dir =
new (Mem) OMPForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
return Dir;
}
@@ -1423,10 +1563,57 @@ OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C,
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective),
llvm::alignOf<OMPClause *>());
void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
return new (Mem) OMPForDirective(CollapsedNum, NumClauses);
}
+OMPForSimdDirective *
+OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
+ OMPForSimdDirective *Dir = new (Mem)
+ OMPForSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ return Dir;
+}
+
+OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
+ return new (Mem) OMPForSimdDirective(CollapsedNum, NumClauses);
+}
+
OMPSectionsDirective *OMPSectionsDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
@@ -1537,19 +1724,36 @@ OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPCriticalDirective();
}
-OMPParallelForDirective *
-OMPParallelForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc, unsigned CollapsedNum,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt) {
+OMPParallelForDirective *OMPParallelForDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective),
llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_parallel_for));
OMPParallelForDirective *Dir = new (Mem)
OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
return Dir;
}
@@ -1558,11 +1762,57 @@ OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective),
llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_parallel_for));
return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses);
}
+OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
+ OMPParallelForSimdDirective *Dir = new (Mem) OMPParallelForSimdDirective(
+ StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond, Exprs.SeparatedCond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ return Dir;
+}
+
+OMPParallelForSimdDirective *
+OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
+ return new (Mem) OMPParallelForSimdDirective(CollapsedNum, NumClauses);
+}
+
OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
@@ -1678,3 +1928,103 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPFlushDirective(NumClauses);
}
+OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ OMPOrderedDirective *Dir = new (Mem) OMPOrderedDirective(StartLoc, EndLoc);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ return new (Mem) OMPOrderedDirective();
+}
+
+OMPAtomicDirective *
+OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ 4 * sizeof(Stmt *));
+ OMPAtomicDirective *Dir =
+ new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setX(X);
+ Dir->setV(V);
+ Dir->setExpr(E);
+ return Dir;
+}
+
+OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 4 * sizeof(Stmt *));
+ return new (Mem) OMPAtomicDirective(NumClauses);
+}
+
+OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTargetDirective *Dir =
+ new (Mem) OMPTargetDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPTargetDirective(NumClauses);
+}
+
+OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTeamsDirective *Dir =
+ new (Mem) OMPTeamsDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPTeamsDirective(NumClauses);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
index 1fdad9f..927a679 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
@@ -665,6 +665,22 @@ void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) {
OS << "mergeable";
}
+void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; }
+
+void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; }
+
+void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) {
+ OS << "update";
+}
+
+void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) {
+ OS << "capture";
+}
+
+void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+ OS << "seq_cst";
+}
+
template<typename T>
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
for (typename T::varlist_iterator I = Node->varlist_begin(),
@@ -820,6 +836,11 @@ void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPForSimdDirective(OMPForSimdDirective *Node) {
+ Indent() << "#pragma omp for simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPSectionsDirective(OMPSectionsDirective *Node) {
Indent() << "#pragma omp sections ";
PrintOMPExecutableDirective(Node);
@@ -855,6 +876,12 @@ void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPParallelForSimdDirective(
+ OMPParallelForSimdDirective *Node) {
+ Indent() << "#pragma omp parallel for simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPParallelSectionsDirective(
OMPParallelSectionsDirective *Node) {
Indent() << "#pragma omp parallel sections ";
@@ -886,6 +913,26 @@ void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) {
+ Indent() << "#pragma omp ordered";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPAtomicDirective(OMPAtomicDirective *Node) {
+ Indent() << "#pragma omp atomic ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) {
+ Indent() << "#pragma omp target ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
+ Indent() << "#pragma omp teams ";
+ PrintOMPExecutableDirective(Node);
+}
+
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
@@ -957,28 +1004,7 @@ void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
}
void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
- switch (Node->getIdentType()) {
- default:
- llvm_unreachable("unknown case");
- case PredefinedExpr::Func:
- OS << "__func__";
- break;
- case PredefinedExpr::Function:
- OS << "__FUNCTION__";
- break;
- case PredefinedExpr::FuncDName:
- OS << "__FUNCDNAME__";
- break;
- case PredefinedExpr::FuncSig:
- OS << "__FUNCSIG__";
- break;
- case PredefinedExpr::LFunction:
- OS << "L__FUNCTION__";
- break;
- case PredefinedExpr::PrettyFunction:
- OS << "__PRETTY_FUNCTION__";
- break;
- }
+ OS << PredefinedExpr::getIdentTypeName(Node->getIdentType());
}
void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
@@ -1716,6 +1742,8 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
case LCK_ByCopy:
OS << C->getCapturedVar()->getName();
break;
+ case LCK_VLAType:
+ llvm_unreachable("VLA type in explicit captures.");
}
if (C->isInitCapture())
@@ -1994,6 +2022,20 @@ void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
PrintExpr(Node->GetTemporaryExpr());
}
+void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) {
+ OS << "(";
+ if (E->getLHS()) {
+ PrintExpr(E->getLHS());
+ OS << " " << BinaryOperator::getOpcodeStr(E->getOperator()) << " ";
+ }
+ OS << "...";
+ if (E->getRHS()) {
+ OS << " " << BinaryOperator::getOpcodeStr(E->getOperator()) << " ";
+ PrintExpr(E->getRHS());
+ }
+ OS << ")";
+}
+
// Obj-C
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
@@ -2138,6 +2180,11 @@ void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
PrintExpr(Node->getSourceExpr());
}
+void StmtPrinter::VisitTypoExpr(TypoExpr *Node) {
+ // TODO: Print something reasonable for a TypoExpr, if necessary.
+ assert(false && "Cannot print TypoExpr nodes");
+}
+
void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) {
OS << "__builtin_astype(";
PrintExpr(Node->getSrcExpr());
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
index f44f25c..d1f25d6 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
@@ -310,18 +310,38 @@ void OMPClauseProfiler::VisitOMPUntiedClause(const OMPUntiedClause *) {}
void OMPClauseProfiler::VisitOMPMergeableClause(const OMPMergeableClause *) {}
+void OMPClauseProfiler::VisitOMPReadClause(const OMPReadClause *) {}
+
+void OMPClauseProfiler::VisitOMPWriteClause(const OMPWriteClause *) {}
+
+void OMPClauseProfiler::VisitOMPUpdateClause(const OMPUpdateClause *) {}
+
+void OMPClauseProfiler::VisitOMPCaptureClause(const OMPCaptureClause *) {}
+
+void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
+
template<typename T>
void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
- for (auto *I : Node->varlists())
- Profiler->VisitStmt(I);
+ for (auto *E : Node->varlists()) {
+ Profiler->VisitStmt(E);
+ }
}
void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->private_copies()) {
+ Profiler->VisitStmt(E);
+ }
}
-void OMPClauseProfiler::VisitOMPFirstprivateClause(
- const OMPFirstprivateClause *C) {
+void
+OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->private_copies()) {
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->inits()) {
+ Profiler->VisitStmt(E);
+ }
}
void
OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) {
@@ -368,16 +388,24 @@ StmtProfiler::VisitOMPExecutableDirective(const OMPExecutableDirective *S) {
P.Visit(*I);
}
+void StmtProfiler::VisitOMPLoopDirective(const OMPLoopDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitOMPParallelDirective(const OMPParallelDirective *S) {
VisitOMPExecutableDirective(S);
}
void StmtProfiler::VisitOMPSimdDirective(const OMPSimdDirective *S) {
- VisitOMPExecutableDirective(S);
+ VisitOMPLoopDirective(S);
}
void StmtProfiler::VisitOMPForDirective(const OMPForDirective *S) {
- VisitOMPExecutableDirective(S);
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPForSimdDirective(const OMPForSimdDirective *S) {
+ VisitOMPLoopDirective(S);
}
void StmtProfiler::VisitOMPSectionsDirective(const OMPSectionsDirective *S) {
@@ -403,7 +431,12 @@ void StmtProfiler::VisitOMPCriticalDirective(const OMPCriticalDirective *S) {
void
StmtProfiler::VisitOMPParallelForDirective(const OMPParallelForDirective *S) {
- VisitOMPExecutableDirective(S);
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPParallelForSimdDirective(
+ const OMPParallelForSimdDirective *S) {
+ VisitOMPLoopDirective(S);
}
void StmtProfiler::VisitOMPParallelSectionsDirective(
@@ -431,6 +464,22 @@ void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPOrderedDirective(const OMPOrderedDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPAtomicDirective(const OMPAtomicDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPTargetDirective(const OMPTargetDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDirective(const OMPTeamsDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
@@ -452,6 +501,7 @@ void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) {
VisitExpr(S);
S->getValue().Profile(ID);
+ ID.AddInteger(S->getType()->castAs<BuiltinType>()->getKind());
}
void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) {
@@ -464,6 +514,7 @@ void StmtProfiler::VisitFloatingLiteral(const FloatingLiteral *S) {
VisitExpr(S);
S->getValue().Profile(ID);
ID.AddBoolean(S->isExact());
+ ID.AddInteger(S->getType()->castAs<BuiltinType>()->getKind());
}
void StmtProfiler::VisitImaginaryLiteral(const ImaginaryLiteral *S) {
@@ -1018,6 +1069,8 @@ StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
VisitDecl(C->getCapturedVar());
ID.AddBoolean(C->isPackExpansion());
break;
+ case LCK_VLAType:
+ llvm_unreachable("VLA type in explicit captures.");
}
}
// Note: If we actually needed to be able to match lambda
@@ -1187,10 +1240,19 @@ void StmtProfiler::VisitMaterializeTemporaryExpr(
VisitExpr(S);
}
+void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getOperator());
+}
+
void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
VisitExpr(E);
}
+void StmtProfiler::VisitTypoExpr(const TypoExpr *E) {
+ VisitExpr(E);
+}
+
void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) {
VisitExpr(S);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
index ac6a754..f8b73cb 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
@@ -33,11 +33,26 @@ using namespace clang;
/// \param TemplArg the TemplateArgument instance to print.
///
/// \param Out the raw_ostream instance to use for printing.
+///
+/// \param Policy the printing policy for EnumConstantDecl printing.
static void printIntegral(const TemplateArgument &TemplArg,
- raw_ostream &Out) {
+ raw_ostream &Out, const PrintingPolicy& Policy) {
const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
const llvm::APSInt &Val = TemplArg.getAsIntegral();
+ if (const EnumType *ET = T->getAs<EnumType>()) {
+ for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) {
+ // In Sema::CheckTemplateArugment, enum template arguments value are
+ // extended to the size of the integer underlying the enum type. This
+ // may create a size difference between the enum value and template
+ // argument value, requiring isSameValue here instead of operator==.
+ if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
+ ECD->printQualifiedName(Out, Policy);
+ return;
+ }
+ }
+ }
+
if (T->isBooleanType()) {
Out << (Val.getBoolValue() ? "true" : "false");
} else if (T->isCharType()) {
@@ -90,7 +105,8 @@ bool TemplateArgument::isDependent() const {
llvm_unreachable("Should not have a NULL template argument");
case Type:
- return getAsType()->isDependentType();
+ return getAsType()->isDependentType() ||
+ isa<PackExpansionType>(getAsType());
case Template:
return getAsTemplate().isDependent();
@@ -111,7 +127,8 @@ bool TemplateArgument::isDependent() const {
return false;
case Expression:
- return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
+ return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() ||
+ isa<PackExpansionExpr>(getAsExpr()));
case Pack:
for (const auto &P : pack_elements())
@@ -294,8 +311,7 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
return TypeOrValue.V == Other.TypeOrValue.V;
case Declaration:
- return getAsDecl() == Other.getAsDecl() &&
- isDeclForReferenceParam() && Other.isDeclForReferenceParam();
+ return getAsDecl() == Other.getAsDecl();
case Integral:
return getIntegralType() == Other.getIntegralType() &&
@@ -377,7 +393,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
break;
case Integral: {
- printIntegral(*this, Out);
+ printIntegral(*this, Out, Policy);
break;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp
index 1677874..e4f364d 100644
--- a/contrib/llvm/tools/clang/lib/AST/Type.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp
@@ -70,7 +70,7 @@ bool QualType::isConstant(QualType T, ASTContext &Ctx) {
if (const ArrayType *AT = Ctx.getAsArrayType(T))
return AT->getElementType().isConstant(Ctx);
- return false;
+ return T.getAddressSpace() == LangAS::opencl_constant;
}
unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context,
@@ -378,9 +378,10 @@ bool Type::isInterfaceType() const {
return false;
}
bool Type::isStructureOrClassType() const {
- if (const RecordType *RT = getAs<RecordType>())
- return RT->getDecl()->isStruct() || RT->getDecl()->isClass() ||
- RT->getDecl()->isInterface();
+ if (const RecordType *RT = getAs<RecordType>()) {
+ RecordDecl *RD = RT->getDecl();
+ return RD->isStruct() || RD->isClass() || RD->isInterface();
+ }
return false;
}
bool Type::isVoidPointerType() const {
@@ -540,10 +541,13 @@ const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const {
}
CXXRecordDecl *Type::getAsCXXRecordDecl() const {
- if (const RecordType *RT = getAs<RecordType>())
- return dyn_cast<CXXRecordDecl>(RT->getDecl());
- else if (const InjectedClassNameType *Injected
- = getAs<InjectedClassNameType>())
+ return dyn_cast_or_null<CXXRecordDecl>(getAsTagDecl());
+}
+
+TagDecl *Type::getAsTagDecl() const {
+ if (const auto *TT = getAs<TagType>())
+ return cast<TagDecl>(TT->getDecl());
+ if (const auto *Injected = getAs<InjectedClassNameType>())
return Injected->getDecl();
return nullptr;
@@ -1147,7 +1151,7 @@ bool Type::isLiteralType(const ASTContext &Ctx) const {
// C++1y [basic.types]p10:
// A type is a literal type if it is:
// -- cv void; or
- if (Ctx.getLangOpts().CPlusPlus1y && isVoidType())
+ if (Ctx.getLangOpts().CPlusPlus14 && isVoidType())
return true;
// C++11 [basic.types]p10:
@@ -1577,6 +1581,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86FastCall: return "fastcall";
case CC_X86ThisCall: return "thiscall";
case CC_X86Pascal: return "pascal";
+ case CC_X86VectorCall: return "vectorcall";
case CC_X86_64Win64: return "ms_abi";
case CC_X86_64SysV: return "sysv_abi";
case CC_AAPCS: return "aapcs";
@@ -1591,18 +1596,21 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
QualType canonical,
const ExtProtoInfo &epi)
- : FunctionType(FunctionProto, result, epi.TypeQuals, canonical,
+ : FunctionType(FunctionProto, result, canonical,
result->isDependentType(),
result->isInstantiationDependentType(),
result->isVariablyModifiedType(),
result->containsUnexpandedParameterPack(), epi.ExtInfo),
- NumParams(params.size()), NumExceptions(epi.NumExceptions),
- ExceptionSpecType(epi.ExceptionSpecType),
+ NumParams(params.size()),
+ NumExceptions(epi.ExceptionSpec.Exceptions.size()),
+ ExceptionSpecType(epi.ExceptionSpec.Type),
HasAnyConsumedParams(epi.ConsumedParameters != nullptr),
- Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn),
- RefQualifier(epi.RefQualifier) {
+ Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) {
assert(NumParams == params.size() && "function has too many parameters");
+ FunctionTypeBits.TypeQuals = epi.TypeQuals;
+ FunctionTypeBits.RefQualifier = epi.RefQualifier;
+
// Fill in the trailing argument array.
QualType *argSlot = reinterpret_cast<QualType*>(this+1);
for (unsigned i = 0; i != NumParams; ++i) {
@@ -1620,36 +1628,38 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
if (getExceptionSpecType() == EST_Dynamic) {
// Fill in the exception array.
QualType *exnSlot = argSlot + NumParams;
- for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) {
- if (epi.Exceptions[i]->isDependentType())
- setDependent();
- else if (epi.Exceptions[i]->isInstantiationDependentType())
+ unsigned I = 0;
+ for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) {
+ // Note that a dependent exception specification does *not* make
+ // a type dependent; it's not even part of the C++ type system.
+ if (ExceptionType->isInstantiationDependentType())
setInstantiationDependent();
-
- if (epi.Exceptions[i]->containsUnexpandedParameterPack())
+
+ if (ExceptionType->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
- exnSlot[i] = epi.Exceptions[i];
+ exnSlot[I++] = ExceptionType;
}
} else if (getExceptionSpecType() == EST_ComputedNoexcept) {
// Store the noexcept expression and context.
Expr **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams);
- *noexSlot = epi.NoexceptExpr;
-
- if (epi.NoexceptExpr) {
- if (epi.NoexceptExpr->isValueDependent()
- || epi.NoexceptExpr->isTypeDependent())
- setDependent();
- else if (epi.NoexceptExpr->isInstantiationDependent())
+ *noexSlot = epi.ExceptionSpec.NoexceptExpr;
+
+ if (epi.ExceptionSpec.NoexceptExpr) {
+ if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||
+ epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())
setInstantiationDependent();
+
+ if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
}
} else if (getExceptionSpecType() == EST_Uninstantiated) {
// Store the function decl from which we will resolve our
// exception specification.
FunctionDecl **slot =
reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
- slot[0] = epi.ExceptionSpecDecl;
- slot[1] = epi.ExceptionSpecTemplate;
+ slot[0] = epi.ExceptionSpec.SourceDecl;
+ slot[1] = epi.ExceptionSpec.SourceTemplate;
// This exception specification doesn't make the type dependent, because
// it's not instantiated as part of instantiating the type.
} else if (getExceptionSpecType() == EST_Unevaluated) {
@@ -1657,7 +1667,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
// exception specification.
FunctionDecl **slot =
reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
- slot[0] = epi.ExceptionSpecDecl;
+ slot[0] = epi.ExceptionSpec.SourceDecl;
}
if (epi.ConsumedParameters) {
@@ -1667,6 +1677,18 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
}
}
+bool FunctionProtoType::hasDependentExceptionSpec() const {
+ if (Expr *NE = getNoexceptExpr())
+ return NE->isValueDependent();
+ for (QualType ET : exceptions())
+ // A pack expansion with a non-dependent pattern is still dependent,
+ // because we don't know whether the pattern is in the exception spec
+ // or not (that depends on whether the pack has 0 expansions).
+ if (ET->isDependentType() || ET->getAs<PackExpansionType>())
+ return true;
+ return false;
+}
+
FunctionProtoType::NoexceptResult
FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {
ExceptionSpecificationType est = getExceptionSpecType();
@@ -1755,20 +1777,21 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
assert(!(unsigned(epi.Variadic) & ~1) &&
!(unsigned(epi.TypeQuals) & ~255) &&
!(unsigned(epi.RefQualifier) & ~3) &&
- !(unsigned(epi.ExceptionSpecType) & ~7) &&
+ !(unsigned(epi.ExceptionSpec.Type) & ~15) &&
"Values larger than expected.");
ID.AddInteger(unsigned(epi.Variadic) +
(epi.TypeQuals << 1) +
(epi.RefQualifier << 9) +
- (epi.ExceptionSpecType << 11));
- if (epi.ExceptionSpecType == EST_Dynamic) {
- for (unsigned i = 0; i != epi.NumExceptions; ++i)
- ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
- } else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){
- epi.NoexceptExpr->Profile(ID, Context, false);
- } else if (epi.ExceptionSpecType == EST_Uninstantiated ||
- epi.ExceptionSpecType == EST_Unevaluated) {
- ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl());
+ (epi.ExceptionSpec.Type << 11));
+ if (epi.ExceptionSpec.Type == EST_Dynamic) {
+ for (QualType Ex : epi.ExceptionSpec.Exceptions)
+ ID.AddPointer(Ex.getAsOpaquePtr());
+ } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept &&
+ epi.ExceptionSpec.NoexceptExpr) {
+ epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, false);
+ } else if (epi.ExceptionSpec.Type == EST_Uninstantiated ||
+ epi.ExceptionSpec.Type == EST_Unevaluated) {
+ ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl());
}
if (epi.ConsumedParameters) {
for (unsigned i = 0; i != NumParams; ++i)
@@ -1909,6 +1932,7 @@ bool AttributedType::isCallingConv() const {
case attr_fastcall:
case attr_stdcall:
case attr_thiscall:
+ case attr_vectorcall:
case attr_pascal:
case attr_ms_abi:
case attr_sysv_abi:
@@ -1976,32 +2000,14 @@ anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N,
return false;
}
-#ifndef NDEBUG
-static bool
-anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N,
- bool &InstantiationDependent) {
- for (unsigned i = 0; i != N; ++i) {
- if (Args[i].isDependent()) {
- InstantiationDependent = true;
- return true;
- }
-
- if (Args[i].isInstantiationDependent())
- InstantiationDependent = true;
- }
- return false;
-}
-#endif
-
TemplateSpecializationType::
TemplateSpecializationType(TemplateName T,
const TemplateArgument *Args, unsigned NumArgs,
QualType Canon, QualType AliasedType)
: Type(TemplateSpecialization,
Canon.isNull()? QualType(this, 0) : Canon,
- Canon.isNull()? T.isDependent() : Canon->isDependentType(),
- Canon.isNull()? T.isDependent()
- : Canon->isInstantiationDependentType(),
+ Canon.isNull()? true : Canon->isDependentType(),
+ Canon.isNull()? true : Canon->isInstantiationDependentType(),
false,
T.containsUnexpandedParameterPack()),
Template(T), NumArgs(NumArgs), TypeAlias(!AliasedType.isNull()) {
@@ -2011,18 +2017,11 @@ TemplateSpecializationType(TemplateName T,
T.getKind() == TemplateName::SubstTemplateTemplateParm ||
T.getKind() == TemplateName::SubstTemplateTemplateParmPack) &&
"Unexpected template name for TemplateSpecializationType");
- bool InstantiationDependent;
- (void)InstantiationDependent;
- assert((!Canon.isNull() ||
- T.isDependent() ||
- ::anyDependentTemplateArguments(Args, NumArgs,
- InstantiationDependent)) &&
- "No canonical type for non-dependent class template specialization");
TemplateArgument *TemplateArgs
= reinterpret_cast<TemplateArgument *>(this + 1);
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- // Update dependent and variably-modified bits.
+ // Update instantiation-dependent and variably-modified bits.
// If the canonical type exists and is non-dependent, the template
// specialization type can be non-dependent even if one of the type
// arguments is. Given:
@@ -2030,17 +2029,13 @@ TemplateSpecializationType(TemplateName T,
// U<T> is always non-dependent, irrespective of the type T.
// However, U<Ts> contains an unexpanded parameter pack, even though
// its expansion (and thus its desugared type) doesn't.
- if (Canon.isNull() && Args[Arg].isDependent())
- setDependent();
- else if (Args[Arg].isInstantiationDependent())
+ if (Args[Arg].isInstantiationDependent())
setInstantiationDependent();
-
if (Args[Arg].getKind() == TemplateArgument::Type &&
Args[Arg].getAsType()->isVariablyModifiedType())
setVariablyModified();
if (Args[Arg].containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
-
new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
index 208d695..c069eb0 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
@@ -312,6 +312,14 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
return TL;
}
+void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
+ ::initializeLocal(Context, Loc);
+ this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
+ getUnderlyingType(), Loc);
+}
+
void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setElaboratedKeywordLoc(Loc);
diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
index 061473e..e36fc17 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
@@ -673,6 +673,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_X86ThisCall:
OS << " __attribute__((thiscall))";
break;
+ case CC_X86VectorCall:
+ OS << " __attribute__((vectorcall))";
+ break;
case CC_X86Pascal:
OS << " __attribute__((pascal))";
break;
@@ -1235,6 +1238,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case AttributedType::attr_fastcall: OS << "fastcall"; break;
case AttributedType::attr_stdcall: OS << "stdcall"; break;
case AttributedType::attr_thiscall: OS << "thiscall"; break;
+ case AttributedType::attr_vectorcall: OS << "vectorcall"; break;
case AttributedType::attr_pascal: OS << "pascal"; break;
case AttributedType::attr_ms_abi: OS << "ms_abi"; break;
case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;
@@ -1428,18 +1432,6 @@ PrintTemplateArgumentList(raw_ostream &OS,
OS << '>';
}
-void QualType::dump(const char *msg) const {
- if (msg)
- llvm::errs() << msg << ": ";
- LangOptions LO;
- print(llvm::errs(), PrintingPolicy(LO), "identifier");
- llvm::errs() << '\n';
-}
-
-LLVM_DUMP_METHOD void QualType::dump() const { dump(nullptr); }
-
-LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
-
std::string Qualifiers::getAsString() const {
LangOptions LO;
return getAsString(PrintingPolicy(LO));
@@ -1498,6 +1490,9 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
case LangAS::opencl_constant:
OS << "__constant";
break;
+ case LangAS::opencl_generic:
+ OS << "__generic";
+ break;
default:
OS << "__attribute__((address_space(";
OS << addrspace;
diff --git a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
index c213d1c..53461eb 100644
--- a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp
@@ -105,7 +105,7 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
CharUnits BaseOffset;
if (I.isVirtual()) {
// Ignore virtual bases that we've already visited.
- if (!VBases.insert(BaseDecl))
+ if (!VBases.insert(BaseDecl).second)
continue;
BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
@@ -157,7 +157,7 @@ void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
// Check if this is a virtual base.
if (I.isVirtual()) {
// Check if we've seen this base before.
- if (!VBases.insert(BaseDecl))
+ if (!VBases.insert(BaseDecl).second)
continue;
CharUnits BaseOffset =
diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
index fa1127f..ddb1f05 100644
--- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
@@ -64,7 +64,7 @@ public:
/// Method - The method decl of the overrider.
const CXXMethodDecl *Method;
- /// VirtualBase - The virtual base class subobject of this overridder.
+ /// VirtualBase - The virtual base class subobject of this overrider.
/// Note that this records the closest derived virtual base class subobject.
const CXXRecordDecl *VirtualBase;
@@ -389,7 +389,7 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base,
CharUnits BaseOffset;
if (B.isVirtual()) {
- if (!VisitedVirtualBases.insert(BaseDecl)) {
+ if (!VisitedVirtualBases.insert(BaseDecl).second) {
// We've visited this base before.
continue;
}
@@ -748,7 +748,7 @@ VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
// Check if this is a virtual base that we haven't visited before.
- if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl)) {
+ if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
CharUnits Offset =
LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass;
@@ -1105,7 +1105,7 @@ namespace {
bool visit(const CXXMethodDecl *MD) {
// Don't recurse on this method if we've already collected it.
- return Methods->insert(MD);
+ return Methods->insert(MD).second;
}
};
}
@@ -1842,7 +1842,7 @@ void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
CharUnits BaseOffsetInLayoutClass;
if (B.isVirtual()) {
- if (!VBases.insert(BaseDecl))
+ if (!VBases.insert(BaseDecl).second)
continue;
const ASTRecordLayout &LayoutClassLayout =
@@ -1870,8 +1870,9 @@ void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
// 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 (B.isVirtual() && BaseDecl->isDynamicClass() &&
- !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) {
+ if (B.isVirtual() && BaseDecl->isDynamicClass() &&
+ !PrimaryVirtualBases.count(BaseDecl) &&
+ VBases.insert(BaseDecl).second) {
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
CharUnits BaseOffset =
@@ -2390,6 +2391,7 @@ namespace {
// first vfptr whose table provides a compatible overridden method. In many
// cases, this permits the original vf-table entry to directly call
// the method instead of passing through a thunk.
+// See example before VFTableBuilder::ComputeThisOffset below.
//
// A compatible overridden method is one which does not have a non-trivial
// covariant-return adjustment.
@@ -2412,6 +2414,9 @@ namespace {
// a) a user-defined ctor/dtor
// and
// b) a method overriding a method in a virtual base.
+//
+// To get a better understanding of this code,
+// you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
class VFTableBuilder {
public:
@@ -2464,11 +2469,18 @@ private:
/// or used for vcalls in the most derived class.
bool Shadowed;
- MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex)
+ /// UsesExtraSlot - Indicates if this vftable slot was created because
+ /// any of the overridden slots required a return adjusting thunk.
+ bool UsesExtraSlot;
+
+ MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
+ bool UsesExtraSlot = false)
: VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
- Shadowed(false) {}
+ Shadowed(false), UsesExtraSlot(UsesExtraSlot) {}
- MethodInfo() : VBTableIndex(0), VFTableIndex(0), Shadowed(false) {}
+ MethodInfo()
+ : VBTableIndex(0), VFTableIndex(0), Shadowed(false),
+ UsesExtraSlot(false) {}
};
typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
@@ -2525,8 +2537,6 @@ private:
}
}
- bool NeedsReturnAdjustingThunk(const CXXMethodDecl *MD);
-
/// AddMethods - Add the methods of this base subobject and the relevant
/// subbases to the vftable we're currently laying out.
void AddMethods(BaseSubobject Base, unsigned BaseDepth,
@@ -2534,13 +2544,15 @@ private:
BasesSetVectorTy &VisitedBases);
void LayoutVFTable() {
- // FIXME: add support for RTTI when we have proper LLVM support for symbols
- // pointing to the middle of a section.
+ // RTTI data goes before all other entries.
+ if (HasRTTIComponent)
+ Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
BasesSetVectorTy VisitedBases;
AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr,
VisitedBases);
- assert(Components.size() && "vftable can't be empty");
+ assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
+ "vftable can't be empty");
assert(MethodVFTableLocations.empty());
for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
@@ -2561,13 +2573,6 @@ private:
}
}
- void ErrorUnsupported(StringRef Feature, SourceLocation Location) {
- clang::DiagnosticsEngine &Diags = Context.getDiagnostics();
- unsigned DiagID = Diags.getCustomDiagID(
- DiagnosticsEngine::Error, "v-table layout for %0 is not supported yet");
- Diags.Report(Context.getFullLoc(Location), DiagID) << Feature;
- }
-
public:
VFTableBuilder(MicrosoftVTableContext &VTables,
const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which)
@@ -2581,8 +2586,6 @@ public:
// definition of the vftable.
HasRTTIComponent = Context.getLangOpts().RTTIData &&
!MostDerivedClass->hasAttr<DLLImportAttr>();
- if (HasRTTIComponent)
- Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
LayoutVFTable();
@@ -2634,7 +2637,7 @@ struct InitialOverriddenDefinitionCollector {
if (OverriddenMD->size_overridden_methods() == 0)
Bases.insert(OverriddenMD->getParent());
// Don't recurse on this method if we've already collected it.
- return VisitedOverriddenMethods.insert(OverriddenMD);
+ return VisitedOverriddenMethods.insert(OverriddenMD).second;
}
};
@@ -2644,6 +2647,60 @@ static bool BaseInSet(const CXXBaseSpecifier *Specifier,
return Bases->count(Specifier->getType()->getAsCXXRecordDecl());
}
+// Let's study one class hierarchy as an example:
+// struct A {
+// virtual void f();
+// int x;
+// };
+//
+// struct B : virtual A {
+// virtual void f();
+// };
+//
+// Record layouts:
+// struct A:
+// 0 | (A vftable pointer)
+// 4 | int x
+//
+// struct B:
+// 0 | (B vbtable pointer)
+// 4 | struct A (virtual base)
+// 4 | (A vftable pointer)
+// 8 | int x
+//
+// Let's assume we have a pointer to the A part of an object of dynamic type B:
+// B b;
+// A *a = (A*)&b;
+// a->f();
+//
+// In this hierarchy, f() belongs to the vftable of A, so B::f() expects
+// "this" parameter to point at the A subobject, which is B+4.
+// In the B::f() prologue, it adjusts "this" back to B by subtracting 4,
+// performed as a *static* adjustment.
+//
+// Interesting thing happens when we alter the relative placement of A and B
+// subobjects in a class:
+// struct C : virtual B { };
+//
+// C c;
+// A *a = (A*)&c;
+// a->f();
+//
+// Respective record layout is:
+// 0 | (C vbtable pointer)
+// 4 | struct A (virtual base)
+// 4 | (A vftable pointer)
+// 8 | int x
+// 12 | struct B (virtual base)
+// 12 | (B vbtable pointer)
+//
+// The final overrider of f() in class C is still B::f(), so B+4 should be
+// passed as "this" to that code. However, "a" points at B-8, so the respective
+// vftable entry should hold a thunk that adds 12 to the "this" argument before
+// performing a tail call to B::f().
+//
+// With this example in mind, we can now calculate the 'this' argument offset
+// for the given method, relative to the beginning of the MostDerivedClass.
CharUnits
VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
InitialOverriddenDefinitionCollector Collector;
@@ -2723,6 +2780,104 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
return Ret;
}
+// Things are getting even more complex when the "this" adjustment has to
+// use a dynamic offset instead of a static one, or even two dynamic offsets.
+// This is sometimes required when a virtual call happens in the middle of
+// a non-most-derived class construction or destruction.
+//
+// Let's take a look at the following example:
+// struct A {
+// virtual void f();
+// };
+//
+// void foo(A *a) { a->f(); } // Knows nothing about siblings of A.
+//
+// struct B : virtual A {
+// virtual void f();
+// B() {
+// foo(this);
+// }
+// };
+//
+// struct C : virtual B {
+// virtual void f();
+// };
+//
+// Record layouts for these classes are:
+// struct A
+// 0 | (A vftable pointer)
+//
+// struct B
+// 0 | (B vbtable pointer)
+// 4 | (vtordisp for vbase A)
+// 8 | struct A (virtual base)
+// 8 | (A vftable pointer)
+//
+// struct C
+// 0 | (C vbtable pointer)
+// 4 | (vtordisp for vbase A)
+// 8 | struct A (virtual base) // A precedes B!
+// 8 | (A vftable pointer)
+// 12 | struct B (virtual base)
+// 12 | (B vbtable pointer)
+//
+// When one creates an object of type C, the C constructor:
+// - initializes all the vbptrs, then
+// - calls the A subobject constructor
+// (initializes A's vfptr with an address of A vftable), then
+// - calls the B subobject constructor
+// (initializes A's vfptr with an address of B vftable and vtordisp for A),
+// that in turn calls foo(), then
+// - initializes A's vfptr with an address of C vftable and zeroes out the
+// vtordisp
+// FIXME: if a structor knows it belongs to MDC, why doesn't it use a vftable
+// without vtordisp thunks?
+// FIXME: how are vtordisp handled in the presence of nooverride/final?
+//
+// When foo() is called, an object with a layout of class C has a vftable
+// referencing B::f() that assumes a B layout, so the "this" adjustments are
+// incorrect, unless an extra adjustment is done. This adjustment is called
+// "vtordisp adjustment". Vtordisp basically holds the difference between the
+// actual location of a vbase in the layout class and the location assumed by
+// the vftable of the class being constructed/destructed. Vtordisp is only
+// needed if "this" escapes a
+// structor (or we can't prove otherwise).
+// [i.e. vtordisp is a dynamic adjustment for a static adjustment, which is an
+// estimation of a dynamic adjustment]
+//
+// foo() gets a pointer to the A vbase and doesn't know anything about B or C,
+// so it just passes that pointer as "this" in a virtual call.
+// If there was no vtordisp, that would just dispatch to B::f().
+// However, B::f() assumes B+8 is passed as "this",
+// yet the pointer foo() passes along is B-4 (i.e. C+8).
+// An extra adjustment is needed, so we emit a thunk into the B vftable.
+// This vtordisp thunk subtracts the value of vtordisp
+// from the "this" argument (-12) before making a tailcall to B::f().
+//
+// Let's consider an even more complex example:
+// struct D : virtual B, virtual C {
+// D() {
+// foo(this);
+// }
+// };
+//
+// struct D
+// 0 | (D vbtable pointer)
+// 4 | (vtordisp for vbase A)
+// 8 | struct A (virtual base) // A precedes both B and C!
+// 8 | (A vftable pointer)
+// 12 | struct B (virtual base) // B precedes C!
+// 12 | (B vbtable pointer)
+// 16 | struct C (virtual base)
+// 16 | (C vbtable pointer)
+//
+// When D::D() calls foo(), we find ourselves in a thunk that should tailcall
+// to C::f(), which assumes C+8 as its "this" parameter. This time, foo()
+// passes along A, which is C-8. The A vtordisp holds
+// "D.vbptr[index_of_A] - offset_of_A_in_D"
+// and we statically know offset_of_A_in_D, so can get a pointer to D.
+// When we know it, we can make an extra vbtable lookup to locate the C vbase
+// and one extra static adjustment to calculate the expected value of C+8.
void VFTableBuilder::CalculateVtordispAdjustment(
FinalOverriders::OverriderInfo Overrider, CharUnits ThisOffset,
ThisAdjustment &TA) {
@@ -2740,9 +2895,9 @@ void VFTableBuilder::CalculateVtordispAdjustment(
// OK, now we know we need to use a vtordisp thunk.
// The implicit vtordisp field is located right before the vbase.
- CharUnits VFPtrVBaseOffset = VBaseMapEntry->second.VBaseOffset;
+ CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
TA.Virtual.Microsoft.VtordispOffset =
- (VFPtrVBaseOffset - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
+ (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
// A simple vtordisp thunk will suffice if the final overrider is defined
// in either the most derived class or its non-virtual base.
@@ -2753,7 +2908,7 @@ void VFTableBuilder::CalculateVtordispAdjustment(
// Otherwise, we need to do use the dynamic offset of the final overrider
// in order to get "this" adjustment right.
TA.Virtual.Microsoft.VBPtrOffset =
- (VFPtrVBaseOffset + WhichVFPtr.NonVirtualOffset -
+ (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
TA.Virtual.Microsoft.VBOffsetOffset =
Context.getTypeSizeInChars(Context.IntTy).getQuantity() *
@@ -2789,24 +2944,6 @@ static void GroupNewVirtualOverloads(
VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend());
}
-/// We need a return adjusting thunk for this method if its return type is
-/// not trivially convertible to the return type of any of its overridden
-/// methods.
-bool VFTableBuilder::NeedsReturnAdjustingThunk(const CXXMethodDecl *MD) {
- OverriddenMethodsSetTy OverriddenMethods;
- ComputeAllOverriddenMethods(MD, OverriddenMethods);
- for (OverriddenMethodsSetTy::iterator I = OverriddenMethods.begin(),
- E = OverriddenMethods.end();
- I != E; ++I) {
- const CXXMethodDecl *OverriddenMD = *I;
- BaseOffset Adjustment =
- ComputeReturnAdjustmentBaseOffset(Context, MD, OverriddenMD);
- if (!Adjustment.isEmpty())
- return true;
- }
- return false;
-}
-
static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) {
for (const auto &B : RD->bases()) {
if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
@@ -2866,20 +3003,21 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
for (unsigned I = 0, E = VirtualMethods.size(); I != E; ++I) {
const CXXMethodDecl *MD = VirtualMethods[I];
- FinalOverriders::OverriderInfo Overrider =
+ FinalOverriders::OverriderInfo FinalOverrider =
Overriders.getOverrider(MD, Base.getBaseOffset());
- const CXXMethodDecl *OverriderMD = Overrider.Method;
+ const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
const CXXMethodDecl *OverriddenMD =
FindNearestOverriddenMethod(MD, VisitedBases);
ThisAdjustment ThisAdjustmentOffset;
- bool ReturnAdjustingThunk = false;
- CharUnits ThisOffset = ComputeThisOffset(Overrider);
+ bool ReturnAdjustingThunk = false, ForceReturnAdjustmentMangling = false;
+ CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
ThisAdjustmentOffset.NonVirtual =
(ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
- if ((OverriddenMD || OverriderMD != MD) &&
+ if ((OverriddenMD || FinalOverriderMD != MD) &&
WhichVFPtr.getVBaseWithVPtr())
- CalculateVtordispAdjustment(Overrider, ThisOffset, ThisAdjustmentOffset);
+ CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
+ ThisAdjustmentOffset);
if (OverriddenMD) {
// If MD overrides anything in this vftable, we need to update the entries.
@@ -2892,7 +3030,16 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
- if (!NeedsReturnAdjustingThunk(MD)) {
+ // Let's check if the overrider requires any return adjustments.
+ // We must create a new slot if the MD's return type is not trivially
+ // convertible to the OverriddenMD's one.
+ // Once a chain of method overrides adds a return adjusting vftable slot,
+ // all subsequent overrides will also use an extra method slot.
+ ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
+ Context, MD, OverriddenMD).isEmpty() ||
+ OverriddenMethodInfo.UsesExtraSlot;
+
+ if (!ReturnAdjustingThunk) {
// No return adjustment needed - just replace the overridden method info
// with the current info.
MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
@@ -2911,8 +3058,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
// Force a special name mangling for a return-adjusting thunk
// unless the method is the final overrider without this adjustment.
- ReturnAdjustingThunk =
- !(MD == OverriderMD && ThisAdjustmentOffset.isEmpty());
+ ForceReturnAdjustmentMangling =
+ !(MD == FinalOverriderMD && ThisAdjustmentOffset.isEmpty());
} else if (Base.getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
MD->size_overridden_methods()) {
// Skip methods that don't belong to the vftable of the current class,
@@ -2926,7 +3073,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
unsigned VBIndex =
LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
MethodInfo MI(VBIndex,
- HasRTTIComponent ? Components.size() - 1 : Components.size());
+ HasRTTIComponent ? Components.size() - 1 : Components.size(),
+ ReturnAdjustingThunk);
assert(!MethodInfoMap.count(MD) &&
"Should not have method info for this method yet!");
@@ -2936,12 +3084,12 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
// We don't want to do this for pure virtual member functions.
BaseOffset ReturnAdjustmentOffset;
ReturnAdjustment ReturnAdjustment;
- if (!OverriderMD->isPure()) {
+ if (!FinalOverriderMD->isPure()) {
ReturnAdjustmentOffset =
- ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
+ ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
}
if (!ReturnAdjustmentOffset.isEmpty()) {
- ReturnAdjustingThunk = true;
+ ForceReturnAdjustmentMangling = true;
ReturnAdjustment.NonVirtual =
ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
if (ReturnAdjustmentOffset.VirtualBase) {
@@ -2955,8 +3103,9 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
}
}
- AddMethod(OverriderMD, ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
- ReturnAdjustingThunk ? MD : nullptr));
+ AddMethod(FinalOverriderMD,
+ ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
+ ForceReturnAdjustmentMangling ? MD : nullptr));
}
}
@@ -3039,10 +3188,8 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
if (MD->isPure())
Out << " [pure]";
- if (MD->isDeleted()) {
- ErrorUnsupported("deleted methods", MD->getLocation());
+ if (MD->isDeleted())
Out << " [deleted]";
- }
ThunkInfo Thunk = VTableThunks.lookup(I);
if (!Thunk.isEmpty())
@@ -3131,7 +3278,7 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
}
static bool setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &A,
- const ArrayRef<const CXXRecordDecl *> &B) {
+ ArrayRef<const CXXRecordDecl *> B) {
for (ArrayRef<const CXXRecordDecl *>::iterator I = B.begin(), E = B.end();
I != E; ++I) {
if (A.count(*I))
@@ -3201,10 +3348,6 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
if (P->MangledPath.empty() || P->MangledPath.back() != Base)
P->NextBaseToMangle = Base;
- // Keep track of the full path.
- // FIXME: Why do we need this?
- P->PathToBaseWithVPtr.insert(P->PathToBaseWithVPtr.begin(), Base);
-
// Keep track of which vtable the derived class is going to extend with
// new methods or bases. We append to either the vftable of our primary
// base, or the first non-virtual base that has a vbtable.
@@ -3292,6 +3435,58 @@ MicrosoftVTableContext::~MicrosoftVTableContext() {
llvm::DeleteContainerSeconds(VBaseInfo);
}
+static bool
+findPathForVPtr(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout,
+ const CXXRecordDecl *RD, CharUnits Offset,
+ llvm::SmallPtrSetImpl<const CXXRecordDecl *> &VBasesSeen,
+ VPtrInfo::BasePath &FullPath, VPtrInfo *Info) {
+ if (RD == Info->BaseWithVPtr && Offset == Info->FullOffsetInMDC) {
+ Info->PathToBaseWithVPtr = FullPath;
+ return true;
+ }
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Recurse with non-virtual bases first.
+ // FIXME: Does this need to be in layout order? Virtual bases will be in base
+ // specifier order, which isn't necessarily layout order.
+ SmallVector<CXXBaseSpecifier, 4> Bases(RD->bases_begin(), RD->bases_end());
+ std::stable_partition(Bases.begin(), Bases.end(),
+ [](CXXBaseSpecifier bs) { return !bs.isVirtual(); });
+
+ for (const auto &B : Bases) {
+ const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
+ CharUnits NewOffset;
+ if (!B.isVirtual())
+ NewOffset = Offset + Layout.getBaseClassOffset(Base);
+ else {
+ if (!VBasesSeen.insert(Base).second)
+ return false;
+ NewOffset = MostDerivedLayout.getVBaseClassOffset(Base);
+ }
+ FullPath.push_back(Base);
+ if (findPathForVPtr(Context, MostDerivedLayout, Base, NewOffset, VBasesSeen,
+ FullPath, Info))
+ return true;
+ FullPath.pop_back();
+ }
+ return false;
+}
+
+static void computeFullPathsForVFTables(ASTContext &Context,
+ const CXXRecordDecl *RD,
+ VPtrInfoVector &Paths) {
+ llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
+ const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
+ VPtrInfo::BasePath FullPath;
+ for (VPtrInfo *Info : Paths) {
+ findPathForVPtr(Context, MostDerivedLayout, RD, CharUnits::Zero(),
+ VBasesSeen, FullPath, Info);
+ VBasesSeen.clear();
+ FullPath.clear();
+ }
+}
+
void MicrosoftVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
assert(RD->isDynamicClass());
@@ -3304,6 +3499,7 @@ void MicrosoftVTableContext::computeVTableRelatedInformation(
VPtrInfoVector *VFPtrs = new VPtrInfoVector();
computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs);
+ computeFullPathsForVFTables(Context, RD, *VFPtrs);
VFPtrLocations[RD] = VFPtrs;
MethodVFTableLocationsTy NewMethodLocations;
OpenPOWER on IntegriCloud