[clang] improve class type sugar preservation in pointers to members (#130537)
This changes the MemberPointerType representation to use a
NestedNameSpecifier instead of a Type to represent the class.
Since the qualifiers are always parsed as nested names, there was an
impedance mismatch when converting these back and forth into types, and
this led to issues in preserving sugar.
The nested names are indeed a better match for these, as the differences
which a QualType can represent cannot be expressed syntactically, and it
also represents the use case more exactly, being either dependent or
referring to a CXXRecord, unqualified.
This patch also makes the MemberPointerType able to represent sugar for
a {up/downcast}cast conversion of the base class, although for now the
underlying type is canonical, as preserving the sugar up to that point
requires further work.
As usual, includes a few drive-by fixes in order to make use of the
improvements, and removing some duplications, for example
CheckBaseClassAccess is deduplicated from across SemaAccess and
SemaCast.diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index 108717e..a6b00be 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -493,8 +493,7 @@
: ClangTidyCheck(Name, Context),
NullMacrosStr(Options.get("NullMacros", "NULL")),
IgnoredTypes(utils::options::parseStringList(Options.get(
- "IgnoredTypes",
- "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
+ "IgnoredTypes", "_CmpUnspecifiedParam;^std::__cmp_cat::__unspec"))) {
StringRef(NullMacrosStr).split(NullMacros, ",");
}
diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index b66cc85..bc49fa8 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -178,7 +178,9 @@
// Note: converting Derived::* to Base::* is a different kind of conversion,
// called Pointer-to-member conversion.
- return FromMember->getClass() == ToMember->getClass() &&
+ return FromMember->getQualifier() == ToMember->getQualifier() &&
+ FromMember->getMostRecentCXXRecordDecl() ==
+ ToMember->getMostRecentCXXRecordDecl() &&
FromMember->getPointeeType() == ToMember->getPointeeType();
}
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index fc54f89..602f61d 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1489,7 +1489,7 @@
"4: targets = {a}\n"
"5: targets = {a::b}, qualifier = 'a::'\n"
"6: targets = {a::b::S}\n"
- "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
+ "7: targets = {a::b::S::type}, qualifier = 'S::'\n"
"8: targets = {y}, decl\n"},
{R"cpp(
void foo() {
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 88862f76..97f6ea90 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -267,6 +267,7 @@
under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``.
- Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
``-Wno-error=parentheses``.
+- Clang now better preserves the sugared types of pointers to member.
- The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
- Fixed diagnostics adding a trailing ``::`` when printing some source code
constructs, like base classes.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index f9a1226..af8c49e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1558,10 +1558,9 @@
QualType getRValueReferenceType(QualType T) const;
/// Return the uniqued reference to the type for a member pointer to
- /// the specified type in the specified class.
- ///
- /// The class \p Cls is a \c Type because it could be a dependent name.
- QualType getMemberPointerType(QualType T, const Type *Cls) const;
+ /// the specified type in the specified nested name.
+ QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
+ const CXXRecordDecl *Cls) const;
/// Return a non-unique reference to the type for a variable array of
/// the specified element type.
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 3bc0bdf..f557555 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -393,7 +393,9 @@
Visit(T->getPointeeType());
}
void VisitMemberPointerType(const MemberPointerType *T) {
- Visit(T->getClass());
+ // FIXME: Provide a NestedNameSpecifier visitor.
+ Visit(T->getQualifier()->getAsType());
+ Visit(T->getMostRecentCXXRecordDecl());
Visit(T->getPointeeType());
}
void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
@@ -485,7 +487,8 @@
}
}
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
- Visit(TL.getClassTInfo()->getTypeLoc());
+ // FIXME: Provide NestedNamespecifierLoc visitor.
+ Visit(TL.getQualifierLoc().getTypeLoc());
}
void VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
Visit(TL.getSizeExpr());
diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h
index 50d1ba1..35db689 100644
--- a/clang/include/clang/AST/CanonicalType.h
+++ b/clang/include/clang/AST/CanonicalType.h
@@ -453,7 +453,7 @@
struct CanProxyAdaptor<MemberPointerType>
: public CanProxyBase<MemberPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
getMostRecentCXXRecordDecl)
};
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 87a6c22..e93d1d8 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1004,7 +1004,8 @@
{ TRY_TO(TraverseType(T->getPointeeType())); })
DEF_TRAVERSE_TYPE(MemberPointerType, {
- TRY_TO(TraverseType(QualType(T->getClass(), 0)));
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
TRY_TO(TraverseType(T->getPointeeType()));
})
@@ -1269,10 +1270,10 @@
// We traverse this in the type case as well, but how is it not reached through
// the pointee type?
DEF_TRAVERSE_TYPELOC(MemberPointerType, {
- if (auto *TSI = TL.getClassTInfo())
- TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+ if (NestedNameSpecifierLoc QL = TL.getQualifierLoc())
+ TRY_TO(TraverseNestedNameSpecifierLoc(QL));
else
- TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
+ TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 3c942f2..6575620 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3527,14 +3527,16 @@
QualType PointeeType;
/// The class of which the pointee is a member. Must ultimately be a
- /// RecordType, but could be a typedef or a template parameter too.
- const Type *Class;
+ /// CXXRecordType, but could be a typedef or a template parameter too.
+ NestedNameSpecifier *Qualifier;
- MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
+ MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
+ QualType CanonicalPtr)
: Type(MemberPointer, CanonicalPtr,
- (Cls->getDependence() & ~TypeDependence::VariablyModified) |
+ (toTypeDependence(Qualifier->getDependence()) &
+ ~TypeDependence::VariablyModified) |
Pointee->getDependence()),
- PointeeType(Pointee), Class(Cls) {}
+ PointeeType(Pointee), Qualifier(Qualifier) {}
public:
QualType getPointeeType() const { return PointeeType; }
@@ -3551,21 +3553,21 @@
return !PointeeType->isFunctionProtoType();
}
- const Type *getClass() const { return Class; }
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
CXXRecordDecl *getMostRecentCXXRecordDecl() const;
- bool isSugared() const { return false; }
- QualType desugar() const { return QualType(this, 0); }
+ bool isSugared() const;
+ QualType desugar() const {
+ return isSugared() ? getCanonicalTypeInternal() : QualType(this, 0);
+ }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getPointeeType(), getClass());
+ Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
- const Type *Class) {
- ID.AddPointer(Pointee.getAsOpaquePtr());
- ID.AddPointer(Class);
- }
+ const NestedNameSpecifier *Qualifier,
+ const CXXRecordDecl *Cls);
static bool classof(const Type *T) {
return T->getTypeClass() == MemberPointer;
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index a55a3833..17ce09f 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -139,6 +139,7 @@
}
/// Get the pointer where source information is stored.
+ // FIXME: This should provide a type-safe interface.
void *getOpaqueData() const {
return Data;
}
@@ -1355,7 +1356,7 @@
};
struct MemberPointerLocInfo : public PointerLikeLocInfo {
- TypeSourceInfo *ClassTInfo;
+ void *QualifierData = nullptr;
};
/// Wrapper for source info for member pointers.
@@ -1371,28 +1372,32 @@
setSigilLoc(Loc);
}
- const Type *getClass() const {
- return getTypePtr()->getClass();
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
+ getLocalData()->QualifierData);
}
- TypeSourceInfo *getClassTInfo() const {
- return getLocalData()->ClassTInfo;
- }
-
- void setClassTInfo(TypeSourceInfo* TI) {
- getLocalData()->ClassTInfo = TI;
+ void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
+ assert(QualifierLoc.getNestedNameSpecifier() ==
+ getTypePtr()->getQualifier() &&
+ "Inconsistent nested-name-specifier pointer");
+ getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setSigilLoc(Loc);
- setClassTInfo(nullptr);
+ if (auto *Qualifier = getTypePtr()->getQualifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, Qualifier, Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+ } else
+ getLocalData()->QualifierData = nullptr;
}
SourceRange getLocalSourceRange() const {
- if (TypeSourceInfo *TI = getClassTInfo())
- return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
- else
- return SourceRange(getStarLoc());
+ if (NestedNameSpecifierLoc QL = getQualifierLoc())
+ return SourceRange(QL.getBeginLoc(), getStarLoc());
+ return SourceRange(getStarLoc());
}
};
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 6f1a76b..27f71bf 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -100,12 +100,15 @@
def : Property<"pointeeType", QualType> {
let Read = [{ node->getPointeeType() }];
}
- def : Property<"baseType", QualType> {
- let Read = [{ QualType(node->getClass(), 0) }];
+ def : Property<"Qualifier", NestedNameSpecifier> {
+ let Read = [{ node->getQualifier() }];
+ }
+ def : Property<"Cls", DeclRef> {
+ let Read = [{ node->getMostRecentCXXRecordDecl() }];
}
def : Creator<[{
- return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
+ return ctx.getMemberPointerType(pointeeType, Qualifier, cast_or_null<CXXRecordDecl>(Cls));
}]>;
}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1536a3b..4cb8f3d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7065,10 +7065,8 @@
"'%0' declared as a member pointer to a reference of type %1">;
def err_illegal_decl_mempointer_to_void : Error<
"'%0' declared as a member pointer to void">;
-def err_illegal_decl_mempointer_in_nonclass : Error<
- "'%0' does not point into a class">;
-def err_mempointer_in_nonclass_type : Error<
- "member pointer refers into non-class type %0">;
+def err_illegal_decl_mempointer_in_nonclass
+ : Error<"'%0' does not point into a class">;
def err_reference_to_void : Error<"cannot form a reference to 'void'">;
def err_nonfunction_block_type : Error<
"block pointer to non-function type is invalid">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9724f0d..e215f07 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1348,6 +1348,12 @@
unsigned DiagID, bool ForceCheck = false,
bool ForceUnprivileged = false);
+ AccessResult CheckBaseClassAccess(
+ SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
+ const CXXBasePath &Path, unsigned DiagID,
+ llvm::function_ref<void(PartialDiagnostic &PD)> SetupPDiag,
+ bool ForceCheck = false, bool ForceUnprivileged = false);
+
/// Checks access to all the declarations in the given result set.
void CheckLookupAccess(const LookupResult &R);
@@ -14879,8 +14885,9 @@
///
/// \returns a member pointer type, if successful, or a NULL type if there was
/// an error.
- QualType BuildMemberPointerType(QualType T, QualType Class,
- SourceLocation Loc, DeclarationName Entity);
+ QualType BuildMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
+ CXXRecordDecl *Cls, SourceLocation Loc,
+ DeclarationName Entity);
/// Build a block pointer type.
///
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 68a02f3..de868ac 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3322,7 +3322,8 @@
case Type::MemberPointer: {
OS << "M";
const auto *MPT = T->castAs<MemberPointerType>();
- encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
+ encodeTypeForFunctionPointerAuth(
+ Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0));
encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
return;
}
@@ -3511,7 +3512,8 @@
if (PointeeType->castAs<FunctionProtoType>()->getExceptionSpecType() !=
EST_None) {
QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
- T = getMemberPointerType(FT, MPT->getClass());
+ T = getMemberPointerType(FT, MPT->getQualifier(),
+ MPT->getMostRecentCXXRecordDecl());
}
}
std::unique_ptr<MangleContext> MC(createMangleContext());
@@ -4025,32 +4027,50 @@
return QualType(New, 0);
}
-/// getMemberPointerType - Return the uniqued reference to the type for a
-/// member pointer to the specified type, in the specified class.
-QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
+QualType ASTContext::getMemberPointerType(QualType T,
+ NestedNameSpecifier *Qualifier,
+ const CXXRecordDecl *Cls) const {
+ if (!Qualifier) {
+ assert(Cls && "At least one of Qualifier or Cls must be provided");
+ Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr,
+ /*Template=*/false,
+ getTypeDeclType(Cls).getTypePtr());
+ } else if (!Cls) {
+ Cls = Qualifier->getAsRecordDecl();
+ }
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
llvm::FoldingSetNodeID ID;
- MemberPointerType::Profile(ID, T, Cls);
+ MemberPointerType::Profile(ID, T, Qualifier, Cls);
void *InsertPos = nullptr;
if (MemberPointerType *PT =
MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
+ NestedNameSpecifier *CanonicalQualifier = [&] {
+ if (!Cls)
+ return getCanonicalNestedNameSpecifier(Qualifier);
+ NestedNameSpecifier *R = NestedNameSpecifier::Create(
+ *this, /*Prefix=*/nullptr, /*Template=*/false,
+ Cls->getCanonicalDecl()->getTypeForDecl());
+ assert(R == getCanonicalNestedNameSpecifier(R));
+ return R;
+ }();
// If the pointee or class type isn't canonical, this won't be a canonical
// type either, so fill in the canonical type field.
QualType Canonical;
- if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
- Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
-
+ if (!T.isCanonical() || Qualifier != CanonicalQualifier) {
+ Canonical =
+ getMemberPointerType(getCanonicalType(T), CanonicalQualifier, Cls);
+ assert(!cast<MemberPointerType>(Canonical)->isSugared());
// Get the new insert position for the node we care about.
- MemberPointerType *NewIP =
- MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
+ [[maybe_unused]] MemberPointerType *NewIP =
+ MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!NewIP && "Shouldn't be in the map!");
}
auto *New = new (*this, alignof(MemberPointerType))
- MemberPointerType(T, Cls, Canonical);
+ MemberPointerType(T, Qualifier, Canonical);
Types.push_back(New);
MemberPointerTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -6812,11 +6832,16 @@
return true;
}
- const auto *T1MPType = T1->getAs<MemberPointerType>();
- const auto *T2MPType = T2->getAs<MemberPointerType>();
- if (T1MPType && T2MPType &&
- hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
- QualType(T2MPType->getClass(), 0))) {
+ if (const auto *T1MPType = T1->getAs<MemberPointerType>(),
+ *T2MPType = T2->getAs<MemberPointerType>();
+ T1MPType && T2MPType) {
+ if (auto *RD1 = T1MPType->getMostRecentCXXRecordDecl(),
+ *RD2 = T2MPType->getMostRecentCXXRecordDecl();
+ RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl())
+ return false;
+ if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) !=
+ getCanonicalNestedNameSpecifier(T2MPType->getQualifier()))
+ return false;
T1 = T1MPType->getPointeeType();
T2 = T2MPType->getPointeeType();
return true;
@@ -13857,11 +13882,12 @@
case Type::MemberPointer: {
const auto *PX = cast<MemberPointerType>(X),
*PY = cast<MemberPointerType>(Y);
+ assert(declaresSameEntity(PX->getMostRecentCXXRecordDecl(),
+ PY->getMostRecentCXXRecordDecl()));
return Ctx.getMemberPointerType(
getCommonPointeeType(Ctx, PX, PY),
- Ctx.getCommonSugaredType(QualType(PX->getClass(), 0),
- QualType(PY->getClass(), 0))
- .getTypePtr());
+ getCommonQualifier(Ctx, PX, PY, /*IsSame=*/true),
+ PX->getMostRecentCXXRecordDecl());
}
case Type::LValueReference: {
const auto *PX = cast<LValueReferenceType>(X),
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 514887a..1db30b3 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1244,12 +1244,16 @@
if (!ToPointeeTypeOrErr)
return ToPointeeTypeOrErr.takeError();
- ExpectedTypePtr ClassTypeOrErr = import(T->getClass());
- if (!ClassTypeOrErr)
- return ClassTypeOrErr.takeError();
+ auto QualifierOrErr = import(T->getQualifier());
+ if (!QualifierOrErr)
+ return QualifierOrErr.takeError();
- return Importer.getToContext().getMemberPointerType(*ToPointeeTypeOrErr,
- *ClassTypeOrErr);
+ auto ClsOrErr = import(T->getMostRecentCXXRecordDecl());
+ if (!ClsOrErr)
+ return ClsOrErr.takeError();
+
+ return Importer.getToContext().getMemberPointerType(
+ *ToPointeeTypeOrErr, *QualifierOrErr, *ClsOrErr);
}
ExpectedType
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index b74f67f..2c2c8fd 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -894,8 +894,12 @@
if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(),
MemPtr2->getPointeeType()))
return false;
- if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0),
- QualType(MemPtr2->getClass(), 0)))
+ if (!IsStructurallyEquivalent(Context, MemPtr1->getQualifier(),
+ MemPtr2->getQualifier()))
+ return false;
+ if (!IsStructurallyEquivalent(Context,
+ MemPtr1->getMostRecentCXXRecordDecl(),
+ MemPtr2->getMostRecentCXXRecordDecl()))
return false;
break;
}
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index c79f3e2..9174025 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3828,7 +3828,16 @@
// <pointer-to-member-type> ::= M <class type> <member type>
void CXXNameMangler::mangleType(const MemberPointerType *T) {
Out << 'M';
- mangleType(QualType(T->getClass(), 0));
+ if (auto *RD = T->getMostRecentCXXRecordDecl()) {
+ mangleCXXRecordDecl(RD);
+ } else {
+ NestedNameSpecifier *NNS = T->getQualifier();
+ if (auto *II = NNS->getAsIdentifier())
+ mangleType(getASTContext().getDependentNameType(
+ ElaboratedTypeKeyword::None, NNS->getPrefix(), II));
+ else
+ manglePrefix(NNS);
+ }
QualType PointeeType = T->getPointeeType();
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
mangleType(FPT);
diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp
index 593f2fc..a256a87 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -297,6 +297,7 @@
PrintingPolicy InnerPolicy(Policy);
InnerPolicy.SuppressScope = true;
+ InnerPolicy.SuppressTagKeyword = true;
// Nested-name-specifiers are intended to contain minimally-qualified
// types. An actual ElaboratedType will not occur, since we'll store
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 7c5c287..4c428cc 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -1076,7 +1076,7 @@
void VisitMemberPointerType(const MemberPointerType *T) {
AddQualType(T->getPointeeType());
- AddType(T->getClass());
+ AddNestedNameSpecifier(T->getQualifier());
VisitType(T);
}
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index e4d2a69..3c814b7 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -391,9 +391,10 @@
Qualifiers Quals = QT.getQualifiers();
// Fully qualify the pointee and class types.
QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
- QualType Class = getFullyQualifiedType(QualType(MPT->getClass(), 0), Ctx,
- WithGlobalNsPrefix);
- QT = Ctx.getMemberPointerType(QT, Class.getTypePtr());
+ NestedNameSpecifier *Qualifier = getFullyQualifiedNestedNameSpecifier(
+ Ctx, MPT->getQualifier(), WithGlobalNsPrefix);
+ QT = Ctx.getMemberPointerType(QT, Qualifier,
+ MPT->getMostRecentCXXRecordDecl());
// Add back the qualifiers.
QT = Ctx.getQualifiedType(QT, Quals);
return QT;
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 33e7008..dee1cb8 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1068,7 +1068,8 @@
if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getMemberPointerType(pointeeType, T->getClass());
+ return Ctx.getMemberPointerType(pointeeType, T->getQualifier(),
+ T->getMostRecentCXXRecordDecl());
}
QualType VisitConstantArrayType(const ConstantArrayType *T) {
@@ -4621,8 +4622,15 @@
return Cache::get(cast<ReferenceType>(T)->getPointeeType());
case Type::MemberPointer: {
const auto *MPT = cast<MemberPointerType>(T);
- return merge(Cache::get(MPT->getClass()),
- Cache::get(MPT->getPointeeType()));
+ CachedProperties Cls = [&] {
+ if (auto *RD = MPT->getMostRecentCXXRecordDecl())
+ return Cache::get(QualType(RD->getTypeForDecl(), 0));
+ if (const Type *T = MPT->getQualifier()->getAsType())
+ return Cache::get(T);
+ // Treat as a dependent type.
+ return CachedProperties(Linkage::External, false);
+ }();
+ return merge(Cls, Cache::get(MPT->getPointeeType()));
}
case Type::ConstantArray:
case Type::IncompleteArray:
@@ -5177,8 +5185,26 @@
return DK_none;
}
+bool MemberPointerType::isSugared() const {
+ CXXRecordDecl *D1 = getMostRecentCXXRecordDecl(),
+ *D2 = getQualifier()->getAsRecordDecl();
+ assert(!D1 == !D2);
+ return D1 != D2 && D1->getCanonicalDecl() != D2->getCanonicalDecl();
+}
+
+void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
+ const NestedNameSpecifier *Qualifier,
+ const CXXRecordDecl *Cls) {
+ ID.AddPointer(Pointee.getAsOpaquePtr());
+ ID.AddPointer(Qualifier);
+ if (Cls)
+ ID.AddPointer(Cls->getCanonicalDecl());
+}
+
CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
- auto *RD = getClass()->getAsCXXRecordDecl();
+ auto *RD = dyn_cast<MemberPointerType>(getCanonicalTypeInternal())
+ ->getQualifier()
+ ->getAsRecordDecl();
if (!RD)
return nullptr;
return RD->getMostRecentNonInjectedDecl();
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index dfd1959..3982ca3 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -505,9 +505,9 @@
PrintingPolicy InnerPolicy(Policy);
InnerPolicy.IncludeTagDefinition = false;
- TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef());
+ T->getQualifier()->print(OS, InnerPolicy);
- OS << "::*";
+ OS << "*";
}
void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index 2777c78d..fd35f2a 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -107,7 +107,7 @@
llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
return GetBogusMemberPointer(CGM.getContext().getMemberPointerType(
- MD->getType(), MD->getParent()->getTypeForDecl()));
+ MD->getType(), /*Qualifier=*/nullptr, MD->getParent()));
}
llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp
index 0c63b9d..4b03230 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -394,8 +394,8 @@
llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD,
llvm::Type *Ty) {
QualType FT = FD->getType();
- FT = getContext().getMemberPointerType(
- FT, cast<CXXMethodDecl>(FD)->getParent()->getTypeForDecl());
+ FT = getContext().getMemberPointerType(FT, /*Qualifier=*/nullptr,
+ cast<CXXMethodDecl>(FD)->getParent());
return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT);
}
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index c910893..c7b3695 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -1400,9 +1400,8 @@
if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer)
continue;
llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType(
- Context.getMemberPointerType(
- Comps[I].getFunctionDecl()->getType(),
- Context.getRecordType(AP.Base).getTypePtr()));
+ Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
+ /*Qualifier=*/nullptr, AP.Base));
VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
}
}
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index f88d620..e26c6c3 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2667,7 +2667,7 @@
for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) {
llvm::Metadata *Id =
CreateMetadataIdentifierForType(Context.getMemberPointerType(
- MD->getType(), Context.getRecordType(Base).getTypePtr()));
+ MD->getType(), /*Qualifier=*/nullptr, Base));
F->addTypeMetadata(0, Id);
}
}
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index a5633f6..77e995b 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -810,9 +810,9 @@
llvm::Value *Bit = Builder.getFalse();
for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
- getContext().getMemberPointerType(
- MPT->getPointeeType(),
- getContext().getRecordType(Base).getTypePtr()));
+ getContext().getMemberPointerType(MPT->getPointeeType(),
+ /*Qualifier=*/nullptr,
+ Base->getCanonicalDecl()));
llvm::Value *TypeId =
llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
@@ -1220,7 +1220,7 @@
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);
QualType SrcType = getContext().getMemberPointerType(
- MD->getType(), MD->getParent()->getTypeForDecl());
+ MD->getType(), /*Qualifier=*/nullptr, MD->getParent());
return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM);
}
@@ -5135,7 +5135,7 @@
.getDecl());
llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);
QualType funcType = CGM.getContext().getMemberPointerType(
- MD->getType(), MD->getParent()->getTypeForDecl());
+ MD->getType(), /*Qualifier=*/nullptr, MD->getParent());
return CGM.getMemberFunctionPointer(thunk, funcType);
}
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 5cb742a..40371d99 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -2928,9 +2928,9 @@
if (!MemberPointerPath.empty()) {
const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext());
- const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr();
const MemberPointerType *SrcTy =
- Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy)
+ Ctx.getMemberPointerType(DstTy->getPointeeType(), /*Qualifier=*/nullptr,
+ SrcRD)
->castAs<MemberPointerType>();
bool DerivedMember = MP.isMemberPointerToDerivedMember();
@@ -3945,7 +3945,8 @@
// for "int A::*" and separately storing the const qualifier.
if (const auto *MPTy = T->getAs<MemberPointerType>())
T = Context.getMemberPointerType(PointeeType.getUnqualifiedType(),
- MPTy->getClass());
+ MPTy->getQualifier(),
+ MPTy->getMostRecentCXXRecordDecl());
// Pointer types like "const int * const *" are represented by having RTTI
// for "const int **" and separately storing the const qualifier.
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index 4ba46a9..b77cbdb 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1873,21 +1873,20 @@
return CheckAccess(*this, Ovl->getNameLoc(), Entity);
}
-Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
- QualType Base, QualType Derived,
- const CXXBasePath &Path,
- unsigned DiagID, bool ForceCheck,
- bool ForceUnprivileged) {
+Sema::AccessResult Sema::CheckBaseClassAccess(
+ SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
+ const CXXBasePath &Path, unsigned DiagID,
+ llvm::function_ref<void(PartialDiagnostic &)> SetupPDiag, bool ForceCheck,
+ bool ForceUnprivileged) {
if (!ForceCheck && !getLangOpts().AccessControl)
return AR_accessible;
if (Path.Access == AS_public)
return AR_accessible;
- AccessTarget Entity(Context, AccessTarget::Base, Base->getAsCXXRecordDecl(),
- Derived->getAsCXXRecordDecl(), Path.Access);
+ AccessTarget Entity(Context, AccessTarget::Base, Base, Derived, Path.Access);
if (DiagID)
- Entity.setDiag(DiagID) << Derived << Base;
+ SetupPDiag(Entity.setDiag(DiagID));
if (ForceUnprivileged) {
switch (
@@ -1904,6 +1903,17 @@
return CheckAccess(*this, AccessLoc, Entity);
}
+Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
+ QualType Base, QualType Derived,
+ const CXXBasePath &Path,
+ unsigned DiagID, bool ForceCheck,
+ bool ForceUnprivileged) {
+ return CheckBaseClassAccess(
+ AccessLoc, Base->getAsCXXRecordDecl(), Derived->getAsCXXRecordDecl(),
+ Path, DiagID, [&](PartialDiagnostic &PD) { PD << Derived << Base; },
+ ForceCheck, ForceUnprivileged);
+}
+
void Sema::CheckLookupAccess(const LookupResult &R) {
assert(getLangOpts().AccessControl
&& "performing access check without access control");
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 718f6be..a5dbc16 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -1788,8 +1788,8 @@
= Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false,
FoundOverload)) {
CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
- SrcType = Self.Context.getMemberPointerType(Fn->getType(),
- Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
+ SrcType = Self.Context.getMemberPointerType(
+ Fn->getType(), /*Qualifier=*/nullptr, M->getParent());
WasOverloadedFunction = true;
}
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 42f0acb..16f0b6d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -14314,9 +14314,8 @@
CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
CheckUseOfCXXMethodAsAddressOfOperand(OpLoc, OrigOp.get(), MD);
-
QualType MPTy = Context.getMemberPointerType(
- op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ op->getType(), DRE->getQualifier(), MD->getParent());
if (getLangOpts().PointerAuthCalls && MD->isVirtual() &&
!isUnevaluatedContext() && !MPTy->isDependentType()) {
@@ -14404,8 +14403,8 @@
// of some class C [...] and if E is a qualified-id, E is
// not the un-parenthesized operand of the unary & operator [...]
// the id-expression is transformed into a class member access expression.
- if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() &&
- !isa<ParenExpr>(OrigOp.get())) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(op);
+ DRE && DRE->getQualifier() && !isa<ParenExpr>(OrigOp.get())) {
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (dcl->getType()->isReferenceType()) {
@@ -14419,8 +14418,7 @@
Ctx = Ctx->getParent();
QualType MPTy = Context.getMemberPointerType(
- op->getType(),
- Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ op->getType(), DRE->getQualifier(), cast<CXXRecordDecl>(Ctx));
// Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(OpLoc, MPTy);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f085fac..90a4a5a 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -7368,6 +7368,7 @@
Qualifiers Quals;
/// The class for a pointer-to-member; a constant array type with a bound
/// (if any) for an array.
+ /// FIXME: Store Qualifier for pointer-to-member.
const Type *ClassOrBound;
Step(Kind K, const Type *ClassOrBound = nullptr)
@@ -7378,7 +7379,8 @@
case Pointer:
return Ctx.getPointerType(T);
case MemberPointer:
- return Ctx.getMemberPointerType(T, ClassOrBound);
+ return Ctx.getMemberPointerType(T, /*Qualifier=*/nullptr,
+ ClassOrBound->getAsCXXRecordDecl());
case ObjCPointer:
return Ctx.getObjCObjectPointerType(T);
case Array:
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 890de83..1c771b0 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -7366,9 +7366,8 @@
QualType FnPtrType;
auto *Method = dyn_cast<CXXMethodDecl>(FD);
if (Method && !Method->isStatic()) {
- const Type *ClassType =
- Context.getTypeDeclType(Method->getParent()).getTypePtr();
- FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
+ FnPtrType = Context.getMemberPointerType(
+ AdjustedFnType, /*Qualifier=*/nullptr, Method->getParent());
ExprResult ER;
{
// Build addr_of unary op to correctly handle type checks for member
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 161c0da..670c27f 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -2243,9 +2243,8 @@
assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode()
== UO_AddrOf &&
"Non-address-of operator on non-static member address");
- const Type *ClassType
- = S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
- FromType = S.Context.getMemberPointerType(FromType, ClassType);
+ FromType = S.Context.getMemberPointerType(
+ FromType, /*Qualifier=*/nullptr, Method->getParent());
} else if (isa<UnaryOperator>(From->IgnoreParens())) {
assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() ==
UO_AddrOf &&
@@ -3293,8 +3292,17 @@
*ToMember = ToType->castAs<MemberPointerType>();
if (!declaresSameEntity(FromMember->getMostRecentCXXRecordDecl(),
ToMember->getMostRecentCXXRecordDecl())) {
- PDiag << ft_different_class << QualType(ToMember->getClass(), 0)
- << QualType(FromMember->getClass(), 0);
+ PDiag << ft_different_class;
+ if (ToMember->isSugared())
+ PDiag << Context.getTypeDeclType(
+ ToMember->getMostRecentCXXRecordDecl());
+ else
+ PDiag << ToMember->getQualifier();
+ if (FromMember->isSugared())
+ PDiag << Context.getTypeDeclType(
+ FromMember->getMostRecentCXXRecordDecl());
+ else
+ PDiag << FromMember->getQualifier();
return;
}
FromType = FromMember->getPointeeType();
@@ -3535,13 +3543,13 @@
// A pointer to member of B can be converted to a pointer to member of D,
// where D is derived from B (C++ 4.11p2).
- QualType FromClass(FromTypePtr->getClass(), 0);
- QualType ToClass(ToTypePtr->getClass(), 0);
+ CXXRecordDecl *FromClass = FromTypePtr->getMostRecentCXXRecordDecl();
+ CXXRecordDecl *ToClass = ToTypePtr->getMostRecentCXXRecordDecl();
- if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
+ if (!declaresSameEntity(FromClass, ToClass) &&
IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass)) {
- ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
- ToClass.getTypePtr());
+ ConvertedType = Context.getMemberPointerType(
+ FromTypePtr->getPointeeType(), FromTypePtr->getQualifier(), ToClass);
return true;
}
@@ -3572,10 +3580,23 @@
ToPtrType->getPointeeType()))
return MemberPointerConversionResult::DifferentPointee;
- QualType FromClass = QualType(FromPtrType->getClass(), 0),
- ToClass = QualType(ToPtrType->getClass(), 0);
+ CXXRecordDecl *FromClass = FromPtrType->getMostRecentCXXRecordDecl(),
+ *ToClass = ToPtrType->getMostRecentCXXRecordDecl();
- QualType Base = FromClass, Derived = ToClass;
+ auto DiagCls = [](PartialDiagnostic &PD, NestedNameSpecifier *Qual,
+ const CXXRecordDecl *Cls) {
+ if (declaresSameEntity(Qual->getAsRecordDecl(), Cls))
+ PD << Qual;
+ else
+ PD << QualType(Cls->getTypeForDecl(), 0);
+ };
+ auto DiagFromTo = [&](PartialDiagnostic &PD) -> PartialDiagnostic & {
+ DiagCls(PD, FromPtrType->getQualifier(), FromClass);
+ DiagCls(PD, ToPtrType->getQualifier(), ToClass);
+ return PD;
+ };
+
+ CXXRecordDecl *Base = FromClass, *Derived = ToClass;
if (Direction == MemberPointerConversionDirection::Upcast)
std::swap(Base, Derived);
@@ -3584,16 +3605,19 @@
if (!IsDerivedFrom(OpRange.getBegin(), Derived, Base, Paths))
return MemberPointerConversionResult::NotDerived;
- if (Paths.isAmbiguous(Base->getCanonicalTypeUnqualified())) {
- Diag(CheckLoc, diag::err_ambiguous_memptr_conv)
- << int(Direction) << FromClass << ToClass
- << getAmbiguousPathsDisplayString(Paths) << OpRange;
+ if (Paths.isAmbiguous(
+ Base->getTypeForDecl()->getCanonicalTypeUnqualified())) {
+ PartialDiagnostic PD = PDiag(diag::err_ambiguous_memptr_conv);
+ PD << int(Direction);
+ DiagFromTo(PD) << getAmbiguousPathsDisplayString(Paths) << OpRange;
+ Diag(CheckLoc, PD);
return MemberPointerConversionResult::Ambiguous;
}
if (const RecordType *VBase = Paths.getDetectedVirtual()) {
- Diag(CheckLoc, diag::err_memptr_conv_via_virtual)
- << FromClass << ToClass << QualType(VBase, 0) << OpRange;
+ PartialDiagnostic PD = PDiag(diag::err_memptr_conv_via_virtual);
+ DiagFromTo(PD) << QualType(VBase, 0) << OpRange;
+ Diag(CheckLoc, PD);
return MemberPointerConversionResult::Virtual;
}
@@ -3608,7 +3632,15 @@
CheckLoc, Base, Derived, Paths.front(),
Direction == MemberPointerConversionDirection::Upcast
? diag::err_upcast_to_inaccessible_base
- : diag::err_downcast_from_inaccessible_base)) {
+ : diag::err_downcast_from_inaccessible_base,
+ [&](PartialDiagnostic &PD) {
+ NestedNameSpecifier *BaseQual = FromPtrType->getQualifier(),
+ *DerivedQual = ToPtrType->getQualifier();
+ if (Direction == MemberPointerConversionDirection::Upcast)
+ std::swap(BaseQual, DerivedQual);
+ DiagCls(PD, DerivedQual, Derived);
+ DiagCls(PD, BaseQual, Base);
+ })) {
case Sema::AR_accessible:
case Sema::AR_delayed:
case Sema::AR_dependent:
@@ -8727,7 +8759,7 @@
// and those shouldn't have qualifier variants anyway.
if (PointeeTy->isArrayType())
return true;
- const Type *ClassTy = PointerTy->getClass();
+ CXXRecordDecl *Cls = PointerTy->getMostRecentCXXRecordDecl();
// Iterate through all strict supersets of the pointee type's CVR
// qualifiers.
@@ -8737,7 +8769,7 @@
QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
MemberPointerTypes.insert(
- Context.getMemberPointerType(QPointeeTy, ClassTy));
+ Context.getMemberPointerType(QPointeeTy, /*Qualifier=*/nullptr, Cls));
}
return true;
@@ -16431,16 +16463,17 @@
assert(isa<DeclRefExpr>(SubExpr.get()) &&
"fixed to something other than a decl ref");
- assert(cast<DeclRefExpr>(SubExpr.get())->getQualifier() &&
+ NestedNameSpecifier *Qualifier =
+ cast<DeclRefExpr>(SubExpr.get())->getQualifier();
+ assert(Qualifier &&
"fixed to a member ref with no nested name qualifier");
// We have taken the address of a pointer to member
// function. Perform the computation here so that we get the
// appropriate pointer to member type.
- QualType ClassType
- = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
- QualType MemPtrType
- = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
+ QualType MemPtrType = Context.getMemberPointerType(
+ Fn->getType(), Qualifier,
+ cast<CXXRecordDecl>(Method->getDeclContext()));
// Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index c3c993d..45fb9d0 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5923,8 +5923,12 @@
}
bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType(
- const MemberPointerType* T) {
- return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0));
+ const MemberPointerType *T) {
+ if (Visit(T->getPointeeType()))
+ return true;
+ if (auto *RD = T->getMostRecentCXXRecordDecl())
+ return VisitTagDecl(RD);
+ return VisitNestedNameSpecifier(T->getQualifier());
}
bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType(
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e6ec4a7..c3bec6b 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2127,9 +2127,19 @@
/*DeducedFromArrayBound=*/false, HasDeducedAnyParam);
Result != TemplateDeductionResult::Success)
return Result;
+ const Type *QP = MPP->getQualifier()->getAsType(),
+ *QA = MPA->getQualifier()->getAsType();
+ CXXRecordDecl *ClsP = MPP->getMostRecentCXXRecordDecl(),
+ *ClsA = MPA->getMostRecentCXXRecordDecl();
+ // FIXME: Don't drop the rest of the prefixes here.
+ QualType P = !ClsP || declaresSameEntity(QP->getAsCXXRecordDecl(), ClsP)
+ ? QualType(QP, 0)
+ : S.Context.getTypeDeclType(ClsP);
+ QualType A = !ClsA || declaresSameEntity(QA->getAsCXXRecordDecl(), ClsA)
+ ? QualType(QA, 0)
+ : S.Context.getTypeDeclType(ClsA);
return DeduceTemplateArgumentsByTypeMatch(
- S, TemplateParams, QualType(MPP->getClass(), 0),
- QualType(MPA->getClass(), 0), Info, Deduced, SubTDF,
+ S, TemplateParams, P, A, Info, Deduced, SubTDF,
degradeCallPartialOrderingKind(POK),
/*DeducedFromArrayBound=*/false, HasDeducedAnyParam);
}
@@ -4211,8 +4221,8 @@
if (!R.HasFormOfMemberPointer)
return {};
- return S.Context.getMemberPointerType(Fn->getType(),
- S.Context.getTypeDeclType(Method->getParent()).getTypePtr());
+ return S.Context.getMemberPointerType(
+ Fn->getType(), /*Qualifier=*/nullptr, Method->getParent());
}
if (!R.IsAddressOfOperand) return Fn->getType();
@@ -6833,7 +6843,8 @@
const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced,
Depth, Used);
- MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0),
+ MarkUsedTemplateParameters(Ctx,
+ QualType(MemPtr->getQualifier()->getAsType(), 0),
OnlyDeduced, Depth, Used);
break;
}
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 11943c0..3971738 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2086,7 +2086,7 @@
// an inheritance model, even if it's inside an unused typedef.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
- if (!MPTy->getClass()->isDependentType())
+ if (!MPTy->getQualifier()->isDependent())
(void)isCompleteType(Loc, T);
} else {
@@ -2685,8 +2685,9 @@
return Context.getFunctionType(T, ParamTypes, EPI);
}
-QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
- SourceLocation Loc,
+QualType Sema::BuildMemberPointerType(QualType T,
+ NestedNameSpecifier *Qualifier,
+ CXXRecordDecl *Cls, SourceLocation Loc,
DeclarationName Entity) {
// Verify that we're not building a pointer to pointer to function with
// exception specification.
@@ -2709,11 +2710,6 @@
return QualType();
}
- if (!Class->isDependentType() && !Class->isRecordType()) {
- Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
- return QualType();
- }
-
if (T->isFunctionType() && getLangOpts().OpenCL &&
!getOpenCLOptions().isAvailableOption("__cl_clang_function_pointers",
getLangOpts())) {
@@ -2734,7 +2730,7 @@
if (T->isFunctionType())
adjustMemberFunctionCC(T, /*HasThisPointer=*/true, IsCtorOrDtor, Loc);
- return Context.getMemberPointerType(T, Class.getTypePtr());
+ return Context.getMemberPointerType(T, Qualifier, Cls);
}
QualType Sema::BuildBlockPointerType(QualType T,
@@ -5338,7 +5334,6 @@
case DeclaratorChunk::MemberPointer: {
// The scope spec must refer to a class, or be dependent.
CXXScopeSpec &SS = DeclType.Mem.Scope();
- QualType ClsType;
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
@@ -5348,56 +5343,22 @@
if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
D.setInvalidType(true);
- } else if (S.isDependentScopeSpecifier(SS) ||
- isa_and_nonnull<CXXRecordDecl>(S.computeDeclContext(SS))) {
- NestedNameSpecifier *NNS = SS.getScopeRep();
- NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- ClsType = Context.getDependentNameType(
- ElaboratedTypeKeyword::None, NNSPrefix, NNS->getAsIdentifier());
- break;
-
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- llvm_unreachable("Nested-name-specifier must name a type");
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- const Type *NNSType = NNS->getAsType();
- ClsType = QualType(NNSType, 0);
- // Note: if the NNS has a prefix and ClsType is a nondependent
- // TemplateSpecializationType or a RecordType, then the NNS prefix is
- // NOT included in ClsType; hence we wrap ClsType into an
- // ElaboratedType. NOTE: in particular, no wrap occurs if ClsType
- // already is an Elaborated, DependentName, or
- // DependentTemplateSpecialization.
- if (isa<DependentTemplateSpecializationType>(NNSType)) {
- // FIXME: Rebuild DependentTemplateSpecializationType, adding the
- // Prefix.
- } else if (isa<TemplateSpecializationType, RecordType>(NNSType)) {
- // Either the dependent case (TemplateSpecializationType), or the
- // non-dependent one (RecordType).
- ClsType = Context.getElaboratedType(ElaboratedTypeKeyword::None,
- NNSPrefix, ClsType);
- }
- break;
- }
+ AreDeclaratorChunksValid = false;
+ } else if (auto *RD =
+ dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS));
+ RD || S.isDependentScopeSpecifier(SS)) {
+ T = S.BuildMemberPointerType(T, SS.getScopeRep(), RD, DeclType.Loc,
+ D.getIdentifier());
} else {
S.Diag(DeclType.Mem.Scope().getBeginLoc(),
diag::err_illegal_decl_mempointer_in_nonclass)
<< (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
<< DeclType.Mem.Scope().getRange();
D.setInvalidType(true);
- }
-
- if (!ClsType.isNull())
- T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc,
- D.getIdentifier());
- else
AreDeclaratorChunksValid = false;
+ // FIXME: Maybe we could model these as as a MemberPointerType with a
+ // non-dependent, non-class qualifier anyway.
+ }
if (T.isNull()) {
T = Context.IntTy;
@@ -6184,48 +6145,8 @@
}
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
- const CXXScopeSpec& SS = Chunk.Mem.Scope();
- NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
-
- const Type* ClsTy = TL.getClass();
- QualType ClsQT = QualType(ClsTy, 0);
- TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
- // Now copy source location info into the type loc component.
- TypeLoc ClsTL = ClsTInfo->getTypeLoc();
- switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
- {
- DependentNameTypeLoc DNTLoc = ClsTL.castAs<DependentNameTypeLoc>();
- DNTLoc.setElaboratedKeywordLoc(SourceLocation());
- DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
- DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
- }
- break;
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- if (isa<ElaboratedType>(ClsTy)) {
- ElaboratedTypeLoc ETLoc = ClsTL.castAs<ElaboratedTypeLoc>();
- ETLoc.setElaboratedKeywordLoc(SourceLocation());
- ETLoc.setQualifierLoc(NNSLoc.getPrefix());
- TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
- NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
- } else {
- ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
- }
- break;
-
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- llvm_unreachable("Nested-name-specifier must name a type");
- }
-
- // Finally fill in MemberPointerLocInfo fields.
TL.setStarLoc(Chunk.Mem.StarLoc);
- TL.setClassTInfo(ClsTInfo);
+ TL.setQualifierLoc(Chunk.Mem.Scope().getWithLocInContext(Context));
}
void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Reference);
@@ -7054,7 +6975,8 @@
case MemberPointer: {
const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
QualType New = wrap(C, OldMPT->getPointeeType(), I);
- return C.getMemberPointerType(New, OldMPT->getClass());
+ return C.getMemberPointerType(New, OldMPT->getQualifier(),
+ OldMPT->getMostRecentCXXRecordDecl());
}
case Reference: {
@@ -9333,17 +9255,17 @@
// "Can't ask whether a dependent type is complete");
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
- if (!MPTy->getClass()->isDependentType()) {
+ if (!MPTy->getQualifier()->isDependent()) {
+ QualType T = Context.getTypeDeclType(MPTy->getMostRecentCXXRecordDecl());
if (getLangOpts().CompleteMemberPointers &&
- !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() &&
- RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), Kind,
- diag::err_memptr_incomplete))
+ !MPTy->getMostRecentCXXRecordDecl()->isBeingDefined() &&
+ RequireCompleteType(Loc, T, Kind, diag::err_memptr_incomplete))
return true;
// We lock in the inheritance model once somebody has asked us to ensure
// that a pointer-to-member type is complete.
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
+ (void)isCompleteType(Loc, T);
assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
}
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index b5de98e..5686b9d 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -859,12 +859,13 @@
SourceLocation Sigil);
/// Build a new member pointer type given the pointee type and the
- /// class type it refers into.
+ /// qualifier it refers into.
///
/// By default, performs semantic analysis when building the member pointer
/// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
- SourceLocation Sigil);
+ QualType RebuildMemberPointerType(QualType PointeeType,
+ NestedNameSpecifier *Qualifier,
+ CXXRecordDecl *Cls, SourceLocation Sigil);
QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
SourceLocation ProtocolLAngleLoc,
@@ -5607,31 +5608,30 @@
if (PointeeType.isNull())
return QualType();
- TypeSourceInfo* OldClsTInfo = TL.getClassTInfo();
- TypeSourceInfo *NewClsTInfo = nullptr;
- if (OldClsTInfo) {
- NewClsTInfo = getDerived().TransformType(OldClsTInfo);
- if (!NewClsTInfo)
- return QualType();
- }
-
const MemberPointerType *T = TL.getTypePtr();
- QualType OldClsType = QualType(T->getClass(), 0);
- QualType NewClsType;
- if (NewClsTInfo)
- NewClsType = NewClsTInfo->getType();
- else {
- NewClsType = getDerived().TransformType(OldClsType);
- if (NewClsType.isNull())
+
+ NestedNameSpecifierLoc OldQualifierLoc = TL.getQualifierLoc();
+ NestedNameSpecifierLoc NewQualifierLoc =
+ getDerived().TransformNestedNameSpecifierLoc(OldQualifierLoc);
+ if (!NewQualifierLoc)
+ return QualType();
+
+ CXXRecordDecl *OldCls = T->getMostRecentCXXRecordDecl(), *NewCls = nullptr;
+ if (OldCls) {
+ NewCls = cast_or_null<CXXRecordDecl>(
+ getDerived().TransformDecl(TL.getStarLoc(), OldCls));
+ if (!NewCls)
return QualType();
}
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() ||
- PointeeType != T->getPointeeType() ||
- NewClsType != OldClsType) {
- Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType,
- TL.getStarLoc());
+ if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeType() ||
+ NewQualifierLoc.getNestedNameSpecifier() !=
+ OldQualifierLoc.getNestedNameSpecifier() ||
+ NewCls != OldCls) {
+ Result = getDerived().RebuildMemberPointerType(
+ PointeeType, NewQualifierLoc.getNestedNameSpecifier(), NewCls,
+ TL.getStarLoc());
if (Result.isNull())
return QualType();
}
@@ -5646,7 +5646,7 @@
MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
NewTL.setSigilLoc(TL.getSigilLoc());
- NewTL.setClassTInfo(NewClsTInfo);
+ NewTL.setQualifierLoc(NewQualifierLoc);
return Result;
}
@@ -17040,12 +17040,11 @@
Sigil, getDerived().getBaseEntity());
}
-template<typename Derived>
-QualType
-TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
- QualType ClassType,
- SourceLocation Sigil) {
- return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil,
+template <typename Derived>
+QualType TreeTransform<Derived>::RebuildMemberPointerType(
+ QualType PointeeType, NestedNameSpecifier *Qualifier, CXXRecordDecl *Cls,
+ SourceLocation Sigil) {
+ return SemaRef.BuildMemberPointerType(PointeeType, Qualifier, Cls, Sigil,
getDerived().getBaseEntity());
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 2b03446..e53a30c 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7103,7 +7103,7 @@
void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
TL.setStarLoc(readSourceLocation());
- TL.setClassTInfo(GetTypeSourceInfo());
+ TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
}
void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 9e6da4d..1ffa17d 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -409,7 +409,7 @@
void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
addSourceLocation(TL.getStarLoc());
- Record.AddTypeSourceInfo(TL.getClassTInfo());
+ Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
}
void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
diff --git a/clang/lib/Serialization/TemplateArgumentHasher.cpp b/clang/lib/Serialization/TemplateArgumentHasher.cpp
index 598f098..3c7177b 100644
--- a/clang/lib/Serialization/TemplateArgumentHasher.cpp
+++ b/clang/lib/Serialization/TemplateArgumentHasher.cpp
@@ -317,7 +317,9 @@
void VisitMemberPointerType(const MemberPointerType *T) {
AddQualType(T->getPointeeType());
- AddType(T->getClass());
+ AddType(T->getQualifier()->getAsType());
+ if (auto *RD = T->getMostRecentCXXRecordDecl())
+ AddDecl(RD->getCanonicalDecl());
}
void VisitPackExpansionType(const PackExpansionType *T) {
diff --git a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp
index 5ac55d2..9f0d3ef 100644
--- a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp
+++ b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp
@@ -2452,6 +2452,9 @@
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x0"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "kind": "TemplateTypeParmType",
// CHECK-NEXT: "type": {
@@ -3225,4 +3228,3 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
-
diff --git a/clang/test/AST/ast-dump-templates.cpp b/clang/test/AST/ast-dump-templates.cpp
index 2728dc1..0e0fa73 100644
--- a/clang/test/AST/ast-dump-templates.cpp
+++ b/clang/test/AST/ast-dump-templates.cpp
@@ -146,6 +146,18 @@
// DUMP: `-TemplateArgument structural value '1+2i'
} // namespace test8
+namespace TestMemberPointerPartialSpec {
+ template <class> struct A;
+ template <class T1, class T2> struct A<T1 T2::*>;
+// DUMP-LABEL: NamespaceDecl {{.+}} TestMemberPointerPartialSpec{{$}}
+// DUMP: ClassTemplatePartialSpecializationDecl {{.*}} struct A
+// DUMP-NEXT: |-TemplateArgument type 'type-parameter-0-0 type-parameter-0-1::*'
+// DUMP-NEXT: | `-MemberPointerType {{.+}} 'type-parameter-0-0 type-parameter-0-1::*' dependent
+// DUMP-NEXT: | |-TemplateTypeParmType {{.+}} 'type-parameter-0-1' dependent depth 0 index 1
+// DUMP-NEXT: | |-<<<NULL>>>
+// DUMP-NEXT: | `-TemplateTypeParmType {{.+}} 'type-parameter-0-0' dependent depth 0 index 0
+} // namespace TestMemberPointerPartialSpec
+
// NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py
@@ -6316,6 +6328,232 @@
// JSON-NEXT: ]
// JSON-NEXT: }
// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NamespaceDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 4680,
+// JSON-NEXT: "line": 149,
+// JSON-NEXT: "col": 11,
+// JSON-NEXT: "tokLen": 28
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 4670,
+// JSON-NEXT: "col": 1,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 5335,
+// JSON-NEXT: "line": 159,
+// JSON-NEXT: "col": 1,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "TestMemberPointerPartialSpec",
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "ClassTemplateDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 4737,
+// JSON-NEXT: "line": 150,
+// JSON-NEXT: "col": 27,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 4713,
+// JSON-NEXT: "col": 3,
+// JSON-NEXT: "tokLen": 8
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 4737,
+// JSON-NEXT: "col": 27,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "A",
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 4728,
+// JSON-NEXT: "col": 18,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 4723,
+// JSON-NEXT: "col": 13,
+// JSON-NEXT: "tokLen": 5
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 4723,
+// JSON-NEXT: "col": 13,
+// JSON-NEXT: "tokLen": 5
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "tagUsed": "class",
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "CXXRecordDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 4737,
+// JSON-NEXT: "col": 27,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 4730,
+// JSON-NEXT: "col": 20,
+// JSON-NEXT: "tokLen": 6
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 4737,
+// JSON-NEXT: "col": 27,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "A",
+// JSON-NEXT: "tagUsed": "struct"
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "ClassTemplatePartialSpecializationDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 4779,
+// JSON-NEXT: "line": 151,
+// JSON-NEXT: "col": 40,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 4742,
+// JSON-NEXT: "col": 3,
+// JSON-NEXT: "tokLen": 8
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 4789,
+// JSON-NEXT: "col": 50,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "A",
+// JSON-NEXT: "tagUsed": "struct",
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "type-parameter-0-0 type-parameter-0-1::*"
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "MemberPointerType",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "type-parameter-0-0 type-parameter-0-1::*"
+// JSON-NEXT: },
+// JSON-NEXT: "isDependent": true,
+// JSON-NEXT: "isInstantiationDependent": true,
+// JSON-NEXT: "isData": true,
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmType",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "type-parameter-0-1"
+// JSON-NEXT: },
+// JSON-NEXT: "isDependent": true,
+// JSON-NEXT: "isInstantiationDependent": true,
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 1,
+// JSON-NEXT: "decl": {
+// JSON-NEXT: "id": "0x0"
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x0"
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmType",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "type-parameter-0-0"
+// JSON-NEXT: },
+// JSON-NEXT: "isDependent": true,
+// JSON-NEXT: "isInstantiationDependent": true,
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0,
+// JSON-NEXT: "decl": {
+// JSON-NEXT: "id": "0x0"
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 4758,
+// JSON-NEXT: "col": 19,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 4752,
+// JSON-NEXT: "col": 13,
+// JSON-NEXT: "tokLen": 5
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 4758,
+// JSON-NEXT: "col": 19,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isReferenced": true,
+// JSON-NEXT: "name": "T1",
+// JSON-NEXT: "tagUsed": "class",
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 4768,
+// JSON-NEXT: "col": 29,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 4762,
+// JSON-NEXT: "col": 23,
+// JSON-NEXT: "tokLen": 5
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 4768,
+// JSON-NEXT: "col": 29,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "T2",
+// JSON-NEXT: "tagUsed": "class",
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 1
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
// JSON-NEXT: }
// JSON-NEXT: ]
// JSON-NEXT: }
diff --git a/clang/test/AST/ast-dump-types-json.cpp b/clang/test/AST/ast-dump-types-json.cpp
index fa1fb53..67379ac3 100644
--- a/clang/test/AST/ast-dump-types-json.cpp
+++ b/clang/test/AST/ast-dump-types-json.cpp
@@ -27,10 +27,11 @@
// NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py
+
// CHECK-NOT: {{^}}Dumping
// CHECK: "kind": "TypedefDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 204,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 12,
// CHECK-NEXT: "col": 18,
@@ -38,12 +39,12 @@
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 187,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 7
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 204,
// CHECK-NEXT: "col": 18,
// CHECK-NEXT: "tokLen": 19
// CHECK-NEXT: }
@@ -78,10 +79,11 @@
// CHECK-NEXT: ]
// CHECK-NEXT: }
+
// CHECK-NOT: {{^}}Dumping
// CHECK: "kind": "TypedefDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 239,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 13,
// CHECK-NEXT: "col": 15,
@@ -89,12 +91,12 @@
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 225,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 7
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 239,
// CHECK-NEXT: "col": 15,
// CHECK-NEXT: "tokLen": 19
// CHECK-NEXT: }
@@ -129,10 +131,11 @@
// CHECK-NEXT: ]
// CHECK-NEXT: }
+
// CHECK-NOT: {{^}}Dumping
// CHECK: "kind": "TypedefDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 319,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 16,
// CHECK-NEXT: "col": 22,
@@ -140,12 +143,12 @@
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 298,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 7
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 319,
// CHECK-NEXT: "col": 22,
// CHECK-NEXT: "tokLen": 22
// CHECK-NEXT: }
@@ -212,10 +215,11 @@
// CHECK-NEXT: ]
// CHECK-NEXT: }
+
// CHECK-NOT: {{^}}Dumping
// CHECK: "kind": "TypedefDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 366,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 18,
// CHECK-NEXT: "col": 20,
@@ -223,12 +227,12 @@
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 347,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 7
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 397,
// CHECK-NEXT: "col": 51,
// CHECK-NEXT: "tokLen": 1
// CHECK-NEXT: }
@@ -248,21 +252,164 @@
// CHECK-NEXT: "inner": [
// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "ElaboratedType",
+// CHECK-NEXT: "kind": "RecordType",
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "T"
// CHECK-NEXT: },
+// CHECK-NEXT: "decl": {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "CXXRecordDecl",
+// CHECK-NEXT: "name": "T"
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "CXXRecordDecl",
+// CHECK-NEXT: "loc": {
+// CHECK-NEXT: "offset": 158,
+// CHECK-NEXT: "line": 7,
+// CHECK-NEXT: "col": 8,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: },
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "offset": 151,
+// CHECK-NEXT: "col": 1,
+// CHECK-NEXT: "tokLen": 6
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "offset": 183,
+// CHECK-NEXT: "line": 10,
+// CHECK-NEXT: "col": 1,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "name": "T",
+// CHECK-NEXT: "tagUsed": "struct",
+// CHECK-NEXT: "completeDefinition": true,
+// CHECK-NEXT: "definitionData": {
+// CHECK-NEXT: "canPassInRegisters": true,
+// CHECK-NEXT: "copyAssign": {
+// CHECK-NEXT: "hasConstParam": true,
+// CHECK-NEXT: "implicitHasConstParam": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "copyCtor": {
+// CHECK-NEXT: "hasConstParam": true,
+// CHECK-NEXT: "implicitHasConstParam": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "defaultCtor": {
+// CHECK-NEXT: "exists": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "dtor": {
+// CHECK-NEXT: "irrelevant": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "isAggregate": true,
+// CHECK-NEXT: "isLiteral": true,
+// CHECK-NEXT: "isPOD": true,
+// CHECK-NEXT: "isStandardLayout": true,
+// CHECK-NEXT: "isTrivial": true,
+// CHECK-NEXT: "isTriviallyCopyable": true,
+// CHECK-NEXT: "moveAssign": {
+// CHECK-NEXT: "exists": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "moveCtor": {
+// CHECK-NEXT: "exists": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: }
+// CHECK-NEXT: },
// CHECK-NEXT: "inner": [
// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "RecordType",
-// CHECK-NEXT: "type": {
-// CHECK-NEXT: "qualType": "T"
+// CHECK-NEXT: "kind": "CXXRecordDecl",
+// CHECK-NEXT: "loc": {
+// CHECK-NEXT: "offset": 158,
+// CHECK-NEXT: "line": 7,
+// CHECK-NEXT: "col": 8,
+// CHECK-NEXT: "tokLen": 1
// CHECK-NEXT: },
-// CHECK-NEXT: "decl": {
-// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "CXXRecordDecl",
-// CHECK-NEXT: "name": "T"
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "offset": 151,
+// CHECK-NEXT: "col": 1,
+// CHECK-NEXT: "tokLen": 6
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "offset": 158,
+// CHECK-NEXT: "col": 8,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "isImplicit": true,
+// CHECK-NEXT: "name": "T",
+// CHECK-NEXT: "tagUsed": "struct"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "FieldDecl",
+// CHECK-NEXT: "loc": {
+// CHECK-NEXT: "offset": 168,
+// CHECK-NEXT: "line": 8,
+// CHECK-NEXT: "col": 7,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: },
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "offset": 164,
+// CHECK-NEXT: "col": 3,
+// CHECK-NEXT: "tokLen": 3
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "offset": 168,
+// CHECK-NEXT: "col": 7,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "name": "I",
+// CHECK-NEXT: "type": {
+// CHECK-NEXT: "qualType": "int"
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "CXXMethodDecl",
+// CHECK-NEXT: "loc": {
+// CHECK-NEXT: "offset": 178,
+// CHECK-NEXT: "line": 9,
+// CHECK-NEXT: "col": 8,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: },
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "offset": 173,
+// CHECK-NEXT: "col": 3,
+// CHECK-NEXT: "tokLen": 4
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "offset": 180,
+// CHECK-NEXT: "col": 10,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "name": "F",
+// CHECK-NEXT: "mangledName": "_ZN1T1FEv",
+// CHECK-NEXT: "type": {
+// CHECK-NEXT: "qualType": "void ()"
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
@@ -298,10 +445,11 @@
// CHECK-NEXT: ]
// CHECK-NEXT: }
+
// CHECK-NOT: {{^}}Dumping
// CHECK: "kind": "TypedefDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 416,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 19,
// CHECK-NEXT: "col": 17,
@@ -309,12 +457,12 @@
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 400,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 7
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 416,
// CHECK-NEXT: "col": 17,
// CHECK-NEXT: "tokLen": 25
// CHECK-NEXT: }
@@ -334,21 +482,164 @@
// CHECK-NEXT: "inner": [
// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "ElaboratedType",
+// CHECK-NEXT: "kind": "RecordType",
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "T"
// CHECK-NEXT: },
+// CHECK-NEXT: "decl": {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "CXXRecordDecl",
+// CHECK-NEXT: "name": "T"
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "CXXRecordDecl",
+// CHECK-NEXT: "loc": {
+// CHECK-NEXT: "offset": 158,
+// CHECK-NEXT: "line": 7,
+// CHECK-NEXT: "col": 8,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: },
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "offset": 151,
+// CHECK-NEXT: "col": 1,
+// CHECK-NEXT: "tokLen": 6
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "offset": 183,
+// CHECK-NEXT: "line": 10,
+// CHECK-NEXT: "col": 1,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "name": "T",
+// CHECK-NEXT: "tagUsed": "struct",
+// CHECK-NEXT: "completeDefinition": true,
+// CHECK-NEXT: "definitionData": {
+// CHECK-NEXT: "canPassInRegisters": true,
+// CHECK-NEXT: "copyAssign": {
+// CHECK-NEXT: "hasConstParam": true,
+// CHECK-NEXT: "implicitHasConstParam": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "copyCtor": {
+// CHECK-NEXT: "hasConstParam": true,
+// CHECK-NEXT: "implicitHasConstParam": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "defaultCtor": {
+// CHECK-NEXT: "exists": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "dtor": {
+// CHECK-NEXT: "irrelevant": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "isAggregate": true,
+// CHECK-NEXT: "isLiteral": true,
+// CHECK-NEXT: "isPOD": true,
+// CHECK-NEXT: "isStandardLayout": true,
+// CHECK-NEXT: "isTrivial": true,
+// CHECK-NEXT: "isTriviallyCopyable": true,
+// CHECK-NEXT: "moveAssign": {
+// CHECK-NEXT: "exists": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: },
+// CHECK-NEXT: "moveCtor": {
+// CHECK-NEXT: "exists": true,
+// CHECK-NEXT: "needsImplicit": true,
+// CHECK-NEXT: "simple": true,
+// CHECK-NEXT: "trivial": true
+// CHECK-NEXT: }
+// CHECK-NEXT: },
// CHECK-NEXT: "inner": [
// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "RecordType",
-// CHECK-NEXT: "type": {
-// CHECK-NEXT: "qualType": "T"
+// CHECK-NEXT: "kind": "CXXRecordDecl",
+// CHECK-NEXT: "loc": {
+// CHECK-NEXT: "offset": 158,
+// CHECK-NEXT: "line": 7,
+// CHECK-NEXT: "col": 8,
+// CHECK-NEXT: "tokLen": 1
// CHECK-NEXT: },
-// CHECK-NEXT: "decl": {
-// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "CXXRecordDecl",
-// CHECK-NEXT: "name": "T"
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "offset": 151,
+// CHECK-NEXT: "col": 1,
+// CHECK-NEXT: "tokLen": 6
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "offset": 158,
+// CHECK-NEXT: "col": 8,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "isImplicit": true,
+// CHECK-NEXT: "name": "T",
+// CHECK-NEXT: "tagUsed": "struct"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "FieldDecl",
+// CHECK-NEXT: "loc": {
+// CHECK-NEXT: "offset": 168,
+// CHECK-NEXT: "line": 8,
+// CHECK-NEXT: "col": 7,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: },
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "offset": 164,
+// CHECK-NEXT: "col": 3,
+// CHECK-NEXT: "tokLen": 3
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "offset": 168,
+// CHECK-NEXT: "col": 7,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "name": "I",
+// CHECK-NEXT: "type": {
+// CHECK-NEXT: "qualType": "int"
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "CXXMethodDecl",
+// CHECK-NEXT: "loc": {
+// CHECK-NEXT: "offset": 178,
+// CHECK-NEXT: "line": 9,
+// CHECK-NEXT: "col": 8,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: },
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "offset": 173,
+// CHECK-NEXT: "col": 3,
+// CHECK-NEXT: "tokLen": 4
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "offset": 180,
+// CHECK-NEXT: "col": 10,
+// CHECK-NEXT: "tokLen": 1
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "name": "F",
+// CHECK-NEXT: "mangledName": "_ZN1T1FEv",
+// CHECK-NEXT: "type": {
+// CHECK-NEXT: "qualType": "void ()"
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
@@ -365,10 +656,11 @@
// CHECK-NEXT: ]
// CHECK-NEXT: }
+
// CHECK-NOT: {{^}}Dumping
// CHECK: "kind": "TypedefDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 456,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 21,
// CHECK-NEXT: "col": 13,
@@ -376,12 +668,12 @@
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 444,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 7
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 490,
// CHECK-NEXT: "col": 47,
// CHECK-NEXT: "tokLen": 1
// CHECK-NEXT: }
@@ -437,10 +729,11 @@
// CHECK-NEXT: ]
// CHECK-NEXT: }
+
// CHECK-NOT: {{^}}Dumping
// CHECK: "kind": "TypedefDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 506,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 23,
// CHECK-NEXT: "col": 13,
@@ -448,12 +741,12 @@
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 494,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 7
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 506,
// CHECK-NEXT: "col": 13,
// CHECK-NEXT: "tokLen": 23
// CHECK-NEXT: }
@@ -473,10 +766,11 @@
// CHECK-NEXT: ]
// CHECK-NEXT: }
+
// CHECK-NOT: {{^}}Dumping
// CHECK: "kind": "NamespaceDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 541,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 24,
// CHECK-NEXT: "col": 11,
@@ -484,12 +778,12 @@
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 531,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 9
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 609,
// CHECK-NEXT: "line": 26,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 1
@@ -501,19 +795,19 @@
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "kind": "UsingDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 584,
// CHECK-NEXT: "line": 25,
// CHECK-NEXT: "col": 9,
// CHECK-NEXT: "tokLen": 23
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 576,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 5
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 584,
// CHECK-NEXT: "col": 9,
// CHECK-NEXT: "tokLen": 23
// CHECK-NEXT: }
@@ -524,18 +818,18 @@
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "kind": "UsingShadowDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 584,
// CHECK-NEXT: "col": 9,
// CHECK-NEXT: "tokLen": 23
// CHECK-NEXT: },
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 584,
// CHECK-NEXT: "col": 9,
// CHECK-NEXT: "tokLen": 23
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 584,
// CHECK-NEXT: "col": 9,
// CHECK-NEXT: "tokLen": 23
// CHECK-NEXT: }
diff --git a/clang/test/AST/attr-print-emit.cpp b/clang/test/AST/attr-print-emit.cpp
index 77826f8..66dbc50 100644
--- a/clang/test/AST/attr-print-emit.cpp
+++ b/clang/test/AST/attr-print-emit.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -ast-print | FileCheck %s
-// RUN: %clang -emit-ast -o %t.ast %s
+// RUN: %clang_cc1 -emit-pch -o %t.ast %s
// RUN: %clang_cc1 %t.ast -ast-print | FileCheck %s
// CHECK: void *aa() __attribute__((assume_aligned(64)));
diff --git a/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
index f46a2c9..d0eb9e80d 100644
--- a/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
+++ b/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
@@ -430,8 +430,8 @@
struct RecordDynTypedVoidPointerTest {
struct RecordType {
- int x; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
- int y; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
+ int x; // expected-note{{uninitialized field 'static_cast<RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
+ int y; // expected-note{{uninitialized field 'static_cast<RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
};
void *vptr;
@@ -447,9 +447,9 @@
struct NestedNonVoidDynTypedVoidPointerTest {
struct RecordType {
- int x; // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
- int y; // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
- void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->vptr)'}}
+ int x; // expected-note{{uninitialized field 'static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
+ int y; // expected-note{{uninitialized field 'static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
+ void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->vptr)'}}
};
void *vptr;
diff --git a/clang/test/CXX/class.access/p6.cpp b/clang/test/CXX/class.access/p6.cpp
index 510aaa2..6f26672 100644
--- a/clang/test/CXX/class.access/p6.cpp
+++ b/clang/test/CXX/class.access/p6.cpp
@@ -113,7 +113,7 @@
};
template <class U> void foo(U &, typename U::type) {}
-
+
void test() {
A<int> a;
foo(a, 0);
@@ -176,7 +176,7 @@
};
void test(A &a) {
- if (a) return; // expected-error-re {{'operator void *(test8::A::*)(){{( __attribute__\(\(thiscall\)\))?}} const' is a private member of 'test8::A'}}
+ if (a) return; // expected-error-re {{'operator void *(A::*)(){{( __attribute__\(\(thiscall\)\))?}} const' is a private member of 'test8::A'}}
}
}
diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp
index 282e71b..4d4e2f6 100644
--- a/clang/test/CXX/drs/cwg0xx.cpp
+++ b/clang/test/CXX/drs/cwg0xx.cpp
@@ -859,7 +859,7 @@
// expected-error@-1 {{cannot cast 'struct B' to its private base class 'A'}}
// expected-note@#cwg54-B {{declared private here}}
int A::*smab = static_cast<int A::*>(&B::b);
- // expected-error@-1 {{cannot cast 'cwg54::B' to its private base class 'A'}}
+ // expected-error@-1 {{cannot cast 'B' to its private base class 'A'}}
// expected-note@#cwg54-B {{declared private here}}
B &sba = static_cast<B&>(a);
// expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}}
@@ -868,19 +868,19 @@
// expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}}
// expected-note@#cwg54-B {{declared private here}}
int B::*smba = static_cast<int B::*>(&A::a);
- // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'B'}}
+ // expected-error@-1 {{cannot cast private base class 'A' to 'B'}}
// expected-note@#cwg54-B {{declared private here}}
V &svb = static_cast<V&>(b);
V *spvb = static_cast<V*>(&b);
int V::*smvb = static_cast<int V::*>(&B::b);
- // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}}
+ // expected-error@-1 {{conversion from pointer to member of class 'B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}}
B &sbv = static_cast<B&>(v);
// expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}}
B *spbv = static_cast<B*>(&v);
// expected-error@-1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}}
int B::*smbv = static_cast<int B::*>(&V::v);
- // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}}
+ // expected-error@-1 {{conversion from pointer to member of class 'V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}}
A &cab = (A&)(b);
A *cpab = (A*)(&b);
@@ -892,13 +892,13 @@
V &cvb = (V&)(b);
V *cpvb = (V*)(&b);
int V::*cmvb = (int V::*)(&B::b);
- // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}}
+ // expected-error@-1 {{conversion from pointer to member of class 'B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}}
B &cbv = (B&)(v);
// expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}}
B *cpbv = (B*)(&v);
// expected-error@-1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}}
int B::*cmbv = (int B::*)(&V::v);
- // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}}
+ // expected-error@-1 {{conversion from pointer to member of class 'V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}}
} // namespace cwg54
namespace cwg55 { // cwg55: 2.7
diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp
index 9c72fef..92b9f3a 100644
--- a/clang/test/CXX/drs/cwg13xx.cpp
+++ b/clang/test/CXX/drs/cwg13xx.cpp
@@ -204,7 +204,7 @@
// since-cxx17-note@-2 {{use 'noexcept(false)' instead}}
void (A::*af2)() throw() = &A::f;
// cxx98-14-error@-1 {{target exception specification is not superset of source}}
- // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (A::*)() throw()' with an rvalue of type 'void (cwg1330::A::*)() throw(T)': different exception specifications}}
+ // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (A::*)() throw()' with an rvalue of type 'void (A::*)() throw(T)': different exception specifications}}
#if __cplusplus >= 201103L
static_assert(noexcept(A().g()), "");
@@ -252,7 +252,7 @@
void (B<P>::*bpf3)() = &B<P>::f;
void (B<P>::*bpf4)() throw() = &B<P>::f;
// cxx98-14-error@-1 {{target exception specification is not superset of source}}
- // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (B<P>::*)() throw()' with an rvalue of type 'void (cwg1330::B<cwg1330::P>::*)() throw(T, typename P::type)': different exception specifications}}
+ // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (B<P>::*)() throw()' with an rvalue of type 'void (B<P>::*)() throw(T, typename P::type)': different exception specifications}}
#if __cplusplus >= 201103L
static_assert(noexcept(B<P>().g()), "");
diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp
index a817a1b..3eb7058 100644
--- a/clang/test/CXX/drs/cwg26xx.cpp
+++ b/clang/test/CXX/drs/cwg26xx.cpp
@@ -142,8 +142,8 @@
void f() {
foo fooable; // #cwg2628-fooable
- // since-cxx20-error@#cwg2628-fooable {{call to deleted}}
- // since-cxx20-note@#cwg2628-ctor {{marked deleted here}}
+ // since-cxx20-error@#cwg2628-fooable {{call to deleted}}
+ // since-cxx20-note@#cwg2628-ctor {{marked deleted here}}
}
#endif
} // namespace cwg2628
@@ -336,7 +336,7 @@
void test() {
(&S::f)(1);
- // since-cxx23-error@-1 {{called object type 'void (cwg2687::S::*)(int)' is not a function or function pointer}}
+ // since-cxx23-error@-1 {{called object type 'void (S::*)(int)' is not a function or function pointer}}
(&S::g)(1);
(&S::h)(S(), 1);
}
diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index 4f383aa..b621318 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -98,8 +98,8 @@
void foo() { Templ<Derived> x(&Derived::func); }
// expected-error@-1 {{no matching constructor for initialization of 'Templ<Derived>'}}
-// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'const Templ<Derived>' for 1st argument}}
-// since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'Templ<Derived>' for 1st argument}}
+// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'const Templ<Derived>' for 1st argument}}
+// since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'Templ<Derived>' for 1st argument}}
// expected-note@#cwg203-ex3-Templ-ctor {{candidate template ignored: could not match 'cwg203::ex3::Derived' against 'cwg203::ex3::Base'}}
} // namespace ex3
diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp
index adbf63f..e8e2600 100644
--- a/clang/test/CXX/drs/cwg4xx.cpp
+++ b/clang/test/CXX/drs/cwg4xx.cpp
@@ -1176,7 +1176,7 @@
extern int D::*c;
int A::*d = static_cast<int A::*>(c);
- // expected-error@-1 {{conversion from pointer to member of class 'cwg480::D' to pointer to member of class 'A' via virtual base 'cwg480::B' is not allowed}}
+ // expected-error@-1 {{conversion from pointer to member of class 'D' to pointer to member of class 'A' via virtual base 'cwg480::B' is not allowed}}
D *e;
A *f = e;
diff --git a/clang/test/CXX/drs/cwg7xx.cpp b/clang/test/CXX/drs/cwg7xx.cpp
index a8ab2e2..9ff01f3 100644
--- a/clang/test/CXX/drs/cwg7xx.cpp
+++ b/clang/test/CXX/drs/cwg7xx.cpp
@@ -348,6 +348,5 @@
};
struct Y : X {};
B Y::*pm = &X::d;
-// expected-error@-1 {{cannot initialize a variable of type 'B Y::*' with an rvalue of type 'D cwg794::X::*': different classes ('Y' vs 'cwg794::X')}}
-// FIXME: why diagnostic says just `Y` and not `cwg794::Y`, like `cwg794::X`?
+// expected-error@-1 {{cannot initialize a variable of type 'B Y::*' with an rvalue of type 'D X::*': different classes ('Y' vs 'X')}}
} // namespace cwg794
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
index 629000d..73c7c75 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
@@ -169,7 +169,7 @@
struct Local { static int f() {} }; // precxx17-note {{here}}
X1<&Local::f> x1_no_linkage; // precxx17-error {{non-type template argument refers to function 'f' that does not have linkage}} cxx17-error {{value of type 'int (*)()' is not implicitly convertible to 'int (*)(int)'}}
- X0<&S::NonStaticMember> x0_non_static; // precxx17-error {{non-static data member}} cxx17-error {{value of type 'int addr_of_obj_or_func::S::*' is not implicitly convertible to 'int *'}}
+ X0<&S::NonStaticMember> x0_non_static; // precxx17-error {{non-static data member}} cxx17-error {{value of type 'int S::*' is not implicitly convertible to 'int *'}}
}
}
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
index 034ad49..bf8f1af 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
@@ -223,7 +223,7 @@
template<int (Y::*)(int)> struct X0 {}; // expected-note 0-1{{template parameter is declared here}}
X0<&Y::f> x0a;
X0<&Y::g> x0b;
- X0<&Y::h> x0c; // expected-error-re{{type 'float (pointer_to_member_function::Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' {{.*}} convert{{.*}} 'int (Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}}
+ X0<&Y::h> x0c; // expected-error-re{{type 'float (Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' {{.*}} convert{{.*}} 'int (Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}}
}
// -- For a non-type template-parameter of type pointer to data member,
@@ -238,9 +238,9 @@
X0<&Y::y> x0a;
X0<&Y::x> x0b;
#if __cplusplus <= 201402L
- // expected-error@-2 {{non-type template argument of type 'int pointer_to_member_data::X::*' cannot be converted to a value of type 'int Y::*'}}
+ // expected-error@-2 {{non-type template argument of type 'int Y::*' (aka 'int X::*') cannot be converted to a value of type 'int Y::*'}}
#else
- // expected-error@-4 {{conversion from 'int pointer_to_member_data::X::*' to 'int Y::*' is not allowed in a converted constant expression}}
+ // expected-error@-4 {{conversion from 'int Y::*' (aka 'int X::*') to 'int Y::*' is not allowed in a converted constant expression}}
#endif
// Test qualification conversions
diff --git a/clang/test/Index/print-type.cpp b/clang/test/Index/print-type.cpp
index 35bf511..141895d 100644
--- a/clang/test/Index/print-type.cpp
+++ b/clang/test/Index/print-type.cpp
@@ -163,7 +163,7 @@
// CHECK: DeclRefExpr=i:44:14 [type=int] [typekind=Int] [isPOD=1]
// CHECK: StructDecl=Blob:46:8 (Definition) [type=Blob] [typekind=Record] [isPOD=1] [nbFields=2]
// CHECK: FieldDecl=i:47:7 (Definition) [type=int] [typekind=Int] [isPOD=1]
-// CHECK: VarDecl=member_pointer:50:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [canonicaltype=int Blob::*] [canonicaltypekind=MemberPointer] [isPOD=1]
+// CHECK: VarDecl=member_pointer:50:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [isPOD=1] [pointeetype=int] [pointeekind=Int] [isAnonRecDecl=0]
// CHECK: FunctionDecl=elaboratedNamespaceType:52:42 [type=NS::Type (const NS::Type)] [typekind=FunctionProto] [canonicaltype=NS::Type (NS::Type)] [canonicaltypekind=FunctionProto] [resulttype=NS::Type] [resulttypekind=Elaborated] [args= [const NS::Type] [Elaborated]] [isPOD=0]
// CHECK: NamespaceRef=NS:52:11 [type=] [typekind=Invalid] [isPOD=0]
// CHECK: TypeRef=struct NS::Type:52:23 [type=NS::Type] [typekind=Record] [isPOD=1]
diff --git a/clang/test/SemaCXX/addr-of-overloaded-function.cpp b/clang/test/SemaCXX/addr-of-overloaded-function.cpp
index 99f5ba6..5568bec 100644
--- a/clang/test/SemaCXX/addr-of-overloaded-function.cpp
+++ b/clang/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
int f(double); // expected-note{{candidate function}}
int f(int); // expected-note{{candidate function}}
@@ -139,7 +139,7 @@
template <typename T> struct mcdata {
typedef int result_type;
};
- template <class T>
+ template <class T>
typename mcdata<T>::result_type wrap_mean(mcdata<T> const&);
void add_property(double(*)(mcdata<double> const &)); // expected-note{{candidate function not viable: no overload of 'wrap_mean' matching}}
void f() {
@@ -204,7 +204,7 @@
double foo(int x, float y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}}
double foo(float x) {return 0;} // expected-note {{candidate function has type mismatch at 1st parameter (expected 'int' but has 'float')}}
double foo(int x) {return 0;} // expected-note {{candidate function has different return type ('int' expected but has 'double')}}
-
+
int (*ptr)(int) = &foo; // expected-error {{address of overloaded function 'foo' does not match required type 'int (int)'}}
struct Qualifiers {
@@ -221,20 +221,20 @@
void QualifierTest() {
void (Qualifiers::*X)();
- X = &Qualifiers::C; // expected-error-re {{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (unqualified vs 'const')}}
- X = &Qualifiers::V; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (unqualified vs 'volatile')}}
- X = &Qualifiers::R; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': different qualifiers (unqualified vs '__restrict')}}
- X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (unqualified vs 'const volatile')}}
- X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': different qualifiers (unqualified vs 'const __restrict')}}
- X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': different qualifiers (unqualified vs 'volatile __restrict')}}
- X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': different qualifiers (unqualified vs 'const volatile __restrict')}}
+ X = &Qualifiers::C; // expected-error-re {{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (unqualified vs 'const')}}
+ X = &Qualifiers::V; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (unqualified vs 'volatile')}}
+ X = &Qualifiers::R; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': different qualifiers (unqualified vs '__restrict')}}
+ X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (unqualified vs 'const volatile')}}
+ X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': different qualifiers (unqualified vs 'const __restrict')}}
+ X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': different qualifiers (unqualified vs 'volatile __restrict')}}
+ X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': different qualifiers (unqualified vs 'const volatile __restrict')}}
}
struct Dummy {
void N() {};
};
- void (Qualifiers::*X)() = &Dummy::N; // expected-error-re{{cannot initialize a variable of type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (test1::Dummy::*)(){{( __attribute__\(\(thiscall\)\))?}}': different classes ('Qualifiers' vs 'test1::Dummy')}}
+ void (Qualifiers::*X)() = &Dummy::N; // expected-error-re{{cannot initialize a variable of type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (Dummy::*)(){{( __attribute__\(\(thiscall\)\))?}}': different classes ('Qualifiers' vs 'Dummy')}}
}
template <typename T> class PR16561 {
diff --git a/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp b/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp
index 4330c0c..e84c651 100644
--- a/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp
+++ b/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp
@@ -18,7 +18,7 @@
void foo(C c, int A::* pmf) {
int i = c->*pmf; // expected-error {{use of overloaded operator '->*' is ambiguous}} \
- // expected-note {{built-in candidate operator->*(const struct A *, int struct A::*)}} \
- // expected-note {{built-in candidate operator->*(struct A *, int struct A::*)}}
+ // expected-note {{built-in candidate operator->*(const struct A *, int A::*)}} \
+ // expected-note {{built-in candidate operator->*(struct A *, int A::*)}}
}
diff --git a/clang/test/SemaCXX/calling-conv-compat.cpp b/clang/test/SemaCXX/calling-conv-compat.cpp
index 5a51e34..9bb448f 100644
--- a/clang/test/SemaCXX/calling-conv-compat.cpp
+++ b/clang/test/SemaCXX/calling-conv-compat.cpp
@@ -183,31 +183,31 @@
typedef void (__cdecl C::*memb_c_cdecl)();
typedef void (__thiscall C::*memb_c_thiscall)();
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_default' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_a_default' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}}
void cb_memb_a_default(memb_a_default ptr);
-// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}}
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}}
void cb_memb_a_cdecl(memb_a_cdecl ptr);
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_thiscall' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_a_thiscall' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}}
void cb_memb_a_thiscall(memb_a_thiscall ptr);
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_default' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_b_default' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}}
void cb_memb_b_default(memb_b_default ptr);
-// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}}
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}}
void cb_memb_b_cdecl(memb_b_cdecl ptr);
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_thiscall' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_b_thiscall' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}}
void cb_memb_b_thiscall(memb_b_thiscall ptr);
-// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
-// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
void cb_memb_c_default(memb_c_default ptr);
-// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
-// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
void cb_memb_c_cdecl(memb_c_cdecl ptr);
-// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
-// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+3 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
void cb_memb_c_thiscall(memb_c_thiscall ptr);
void call_member() {
@@ -279,11 +279,11 @@
void cb_memb_a_cdecl(memb_a_cdecl ptr);
void cb_memb_b_default(memb_b_default ptr);
void cb_memb_b_cdecl(memb_b_cdecl ptr);
-// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}}
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (A::*)(int, ...)' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}}
void cb_memb_c_default(memb_c_default ptr);
-// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
-// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
+// expected-note@+2 {{candidate function not viable: no known conversion from 'void (A::*)(int, ...)' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
+// expected-note@+1 {{candidate function not viable: no known conversion from 'void (A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
void cb_memb_c_cdecl(memb_c_cdecl ptr);
void call_member() {
diff --git a/clang/test/SemaCXX/err_init_conversion_failed.cpp b/clang/test/SemaCXX/err_init_conversion_failed.cpp
index e31f215..f1949c0 100644
--- a/clang/test/SemaCXX/err_init_conversion_failed.cpp
+++ b/clang/test/SemaCXX/err_init_conversion_failed.cpp
@@ -56,6 +56,6 @@
void test_15() {
S2<S> X = {&S::foo};
- // expected-error-re@-1{{cannot initialize a member subobject of type 'void (template_test::S::*)(const int &){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (template_test::S::*)(int){{( __attribute__\(\(thiscall\)\))?}}': type mismatch at 1st parameter ('const int &' vs 'int')}}
+ // expected-error-re@-1{{cannot initialize a member subobject of type 'void (S::*)(const int &){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (S::*)(int){{( __attribute__\(\(thiscall\)\))?}}': type mismatch at 1st parameter ('const int &' vs 'int')}}
}
}
diff --git a/clang/test/SemaCXX/member-pointer.cpp b/clang/test/SemaCXX/member-pointer.cpp
index ec27d7a..81a3a3f 100644
--- a/clang/test/SemaCXX/member-pointer.cpp
+++ b/clang/test/SemaCXX/member-pointer.cpp
@@ -48,7 +48,7 @@
// Conversion to member of base.
pdi1 = pdid; // expected-error {{assigning to 'int A::*' from incompatible type 'int D::*'}}
-
+
// Comparisons
int (A::*pf2)(int, int);
int (D::*pf3)(int, int) = 0;
@@ -107,7 +107,7 @@
int i = phm->*pi;
(void)&(hm.*pi);
(void)&(phm->*pi);
- (void)&((&hm)->*pi);
+ (void)&((&hm)->*pi);
void (HasMembers::*pf)() = &HasMembers::f;
(hm.*pf)();
@@ -205,7 +205,7 @@
static void stat();
static void stat(int);
-
+
template <typename T> struct Test0 {
void test() {
bind(&nonstat); // expected-error {{no matching function for call}}
@@ -296,7 +296,7 @@
{ call(u); } // expected-note{{in instantiation of}}
};
- template<class R, class T>
+ template<class R, class T>
dm<R, T> mem_fn(R T::*) ;
struct test
@@ -324,3 +324,12 @@
.**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
}
}
+
+namespace test9 {
+ struct FOO BAR;
+ // expected-error@-1 {{variable has incomplete type 'struct FOO'}}
+ // expected-note@-2 {{forward declaration of 'test9::FOO'}}
+ // expected-note@-3 {{'BAR' declared here}}
+ struct C { int BAR::*mp; };
+ // expected-error@-1 {{'BAR' is not a class, namespace, or enumeration}}
+} // namespace test9
diff --git a/clang/test/SemaOpenACC/combined-construct-if-ast.cpp b/clang/test/SemaOpenACC/combined-construct-if-ast.cpp
index f079640..96c465d 100644
--- a/clang/test/SemaOpenACC/combined-construct-if-ast.cpp
+++ b/clang/test/SemaOpenACC/combined-construct-if-ast.cpp
@@ -88,7 +88,7 @@
// CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float'
// CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy'
// CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <IntegralToFloating>
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
// CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
// CHECK-NEXT: ForStmt
// CHECK: NullStmt
@@ -96,7 +96,7 @@
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop
// CHECK-NEXT: if clause
// CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <IntegralToBoolean>
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
// CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
// CHECK-NEXT: ForStmt
// CHECK: NullStmt
diff --git a/clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp b/clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp
index 8aa361c..a04fcdd 100644
--- a/clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp
+++ b/clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp
@@ -204,14 +204,14 @@
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop
// CHECK-NEXT: num_workers clause
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename struct HasInt::IntTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename HasInt::IntTy <NoOp>
// CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::IntTy':'int'
// CHECK-NEXT: ForStmt
// CHECK: NullStmt
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop
// CHECK-NEXT: num_workers clause
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename struct HasInt::ShortTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename HasInt::ShortTy <NoOp>
// CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::ShortTy':'short'
// CHECK-NEXT: ForStmt
// CHECK: NullStmt
diff --git a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
index 58c12b8..babff53 100644
--- a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
+++ b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
@@ -356,7 +356,7 @@
// CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float'
// CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy'
// CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <IntegralToFloating>
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
// CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
@@ -365,7 +365,7 @@
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial
// CHECK-NEXT: if clause
// CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <IntegralToBoolean>
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
// CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
diff --git a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp
index 2c48fc3..baf7aa6 100644
--- a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp
+++ b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp
@@ -506,7 +506,7 @@
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels
// CHECK-NEXT: num_workers clause
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename struct HasInt::IntTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename HasInt::IntTy <NoOp>
// CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::IntTy':'int'
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
@@ -514,7 +514,7 @@
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel
// CHECK-NEXT: num_workers clause
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename struct HasInt::ShortTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename HasInt::ShortTy <NoOp>
// CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::ShortTy':'short'
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
diff --git a/clang/test/SemaOpenACC/data-construct-if-ast.cpp b/clang/test/SemaOpenACC/data-construct-if-ast.cpp
index 9ceee4e..533a97d 100644
--- a/clang/test/SemaOpenACC/data-construct-if-ast.cpp
+++ b/clang/test/SemaOpenACC/data-construct-if-ast.cpp
@@ -94,7 +94,7 @@
// CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float'
// CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy'
// CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <IntegralToFloating>
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
// CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
// CHECK-NEXT: NullStmt
@@ -103,7 +103,7 @@
// CHECK-NEXT: DeclRefExpr{{.*}}'Global' 'int'
// CHECK-NEXT: if clause
// CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <IntegralToBoolean>
- // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
+ // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
// CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
// CHECK-NEXT: NullStmt
diff --git a/clang/test/SemaTemplate/instantiate-member-pointers.cpp b/clang/test/SemaTemplate/instantiate-member-pointers.cpp
index 4757870..8b6c2ef 100644
--- a/clang/test/SemaTemplate/instantiate-member-pointers.cpp
+++ b/clang/test/SemaTemplate/instantiate-member-pointers.cpp
@@ -5,7 +5,8 @@
template<typename T>
struct X1 {
- int f(T* ptr, int T::*pm) { // expected-error{{member pointer}}
+ int f(T* ptr, int T::*pm) {
+ // expected-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}}
return ptr->*pm;
}
};
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index f4227fd..2c9ef28 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -966,12 +966,14 @@
}
CXType clang_Type_getClassType(CXType CT) {
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(CT))->getASTContext();
QualType ET = QualType();
QualType T = GetQualType(CT);
const Type *TP = T.getTypePtrOrNull();
if (TP && TP->getTypeClass() == Type::MemberPointer) {
- ET = QualType(cast<MemberPointerType> (TP)->getClass(), 0);
+ ET = Ctx.getTypeDeclType(
+ cast<MemberPointerType>(TP)->getMostRecentCXXRecordDecl());
}
return MakeCXType(ET, GetTU(CT));
}
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 068cf66..7484416 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5760,10 +5760,10 @@
TEST(NNS, BindsNestedNameSpecifiers) {
EXPECT_TRUE(matchAndVerifyResultTrue(
- "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
- nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
- std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>(
- "nns", "ns::struct E::")));
+ "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
+ nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
+ std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("nns",
+ "ns::E::")));
}
TEST(NNS, BindsNestedNameSpecifierLocs) {