Modified tests to cover two issues I found when I ran the patch over our code
base at work.
Gentle ping.
http://reviews.llvm.org/D4468
Files:
include/clang/AST/DataRecursiveASTVisitor.h
include/clang/AST/NestedNameSpecifier.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/TokenKinds.def
include/clang/Sema/DeclSpec.h
include/clang/Sema/Sema.h
lib/AST/ASTContext.cpp
lib/AST/ASTImporter.cpp
lib/AST/ExprCXX.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/NestedNameSpecifier.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseTentative.cpp
lib/Parse/Parser.cpp
lib/Sema/DeclSpec.cpp
lib/Sema/SemaCXXScopeSpec.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaLookup.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaType.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/SemaCXX/MicrosoftExtensions.cpp
tools/libclang/CIndex.cpp
tools/libclang/IndexTypeSourceInfo.cpp
Index: include/clang/AST/DataRecursiveASTVisitor.h
===================================================================
--- include/clang/AST/DataRecursiveASTVisitor.h
+++ include/clang/AST/DataRecursiveASTVisitor.h
@@ -624,6 +624,7 @@
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
return true;
case NestedNameSpecifier::TypeSpec:
@@ -648,6 +649,7 @@
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
return true;
case NestedNameSpecifier::TypeSpec:
Index: include/clang/AST/NestedNameSpecifier.h
===================================================================
--- include/clang/AST/NestedNameSpecifier.h
+++ include/clang/AST/NestedNameSpecifier.h
@@ -22,6 +22,7 @@
namespace clang {
class ASTContext;
+class CXXRecordDecl;
class NamespaceAliasDecl;
class NamespaceDecl;
class IdentifierInfo;
@@ -45,7 +46,7 @@
/// \brief Enumeration describing
enum StoredSpecifierKind {
StoredIdentifier = 0,
- StoredNamespaceOrAlias = 1,
+ StoredDecl = 1,
StoredTypeSpec = 2,
StoredTypeSpecWithTemplate = 3
};
@@ -83,7 +84,10 @@
/// stored as a Type*.
TypeSpecWithTemplate,
/// \brief The global specifier '::'. There is no stored value.
- Global
+ Global,
+ /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
+ /// the class it appeared in.
+ MsSuper
};
private:
@@ -143,6 +147,11 @@
/// scope.
static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
+ /// \brief Returns the nested name specifier representing the __super scope
+ /// for the given CXXRecordDecl.
+ static NestedNameSpecifier *MsSuperSpecifier(const ASTContext &Context,
+ CXXRecordDecl *RD);
+
/// \brief Return the prefix of this nested name specifier.
///
/// The prefix contains all of the parts of the nested name
@@ -172,6 +181,10 @@
/// specifier.
NamespaceAliasDecl *getAsNamespaceAlias() const;
+ /// \brief Retrieve the record declaration stored in this nested name
+ /// specifier.
+ CXXRecordDecl *getAsRecordDecl() const;
+
/// \brief Retrieve the type stored in this nested name specifier.
const Type *getAsType() const {
if (Prefix.getInt() == StoredTypeSpec ||
@@ -421,7 +434,22 @@
/// \brief Turn this (empty) nested-name-specifier into the global
/// nested-name-specifier '::'.
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
-
+
+ /// \brief Turns this (empty) nested-name-specifier into '__super'
+ /// nested-name-specifier.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param RD The declaration of the class in which nested-name-specifier
+ /// appeared.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void MakeMsSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc, SourceLocation ColonColonLoc);
/// \brief Make a new nested-name-specifier from incomplete source-location
/// information.
///
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -690,6 +690,7 @@
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
return true;
case NestedNameSpecifier::TypeSpec:
@@ -714,6 +715,7 @@
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
return true;
case NestedNameSpecifier::TypeSpec:
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -368,6 +368,8 @@
"function definition is not allowed here">;
def err_expected_end_of_enumerator : Error<
"expected '= constant-expression' or end of enumerator definition">;
+def err_expected_coloncolon_after_super : Error<
+ "expected '::' after __super">;
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<
@@ -519,6 +521,8 @@
InGroup<DiagGroup<"anonymous-pack-parens">>;
def err_function_is_not_record : Error<
"unexpected %0 in function call; perhaps remove the %0?">;
+def err_super_in_using_declaration : Error<
+ "__super cannot be used with a using declaration">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -524,6 +524,7 @@
"with base classes or virtual functions">,
DefaultError, InGroup<IncompatibleMSStruct>;
def err_section_conflict : Error<"%0 causes a section type conflict with %1">;
+def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">;
def warn_pragma_unused_undeclared_var : Warning<
"undeclared variable %0 used as an argument for '#pragma unused'">,
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def
+++ include/clang/Basic/TokenKinds.def
@@ -459,6 +459,7 @@
KEYWORD(__thiscall , KEYALL)
KEYWORD(__forceinline , KEYMS)
KEYWORD(__unaligned , KEYMS)
+KEYWORD(__super , KEYMS)
// OpenCL address space qualifiers
KEYWORD(__global , KEYOPENCL)
Index: include/clang/Sema/DeclSpec.h
===================================================================
--- include/clang/Sema/DeclSpec.h
+++ include/clang/Sema/DeclSpec.h
@@ -37,6 +37,7 @@
namespace clang {
class ASTContext;
+ class CXXRecordDecl;
class TypeLoc;
class LangOptions;
class DiagnosticsEngine;
@@ -141,6 +142,22 @@
/// nested-name-specifier '::'.
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+ /// \brief Turns this (empty) nested-name-specifier into '__super'
+ /// nested-name-specifier.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param RD The declaration of the class in which nested-name-specifier
+ /// appeared.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void MakeMsSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc, SourceLocation ColonColonLoc);
+
/// \brief Make a new nested-name-specifier from incomplete source-location
/// information.
///
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -2608,6 +2608,7 @@
ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc,
RedeclarationKind Redecl
= NotForRedeclaration);
+ void LookupInMsSuper(LookupResult &R, CXXRecordDecl *Class);
void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
@@ -4476,6 +4477,22 @@
/// \returns true if an error occurred, false otherwise.
bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
CXXScopeSpec &SS);
+
+ /// \brief The parser has parsed a '__super' nested-name-specifier.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ ///
+ /// \param ColonColonLoc The location of the '::'.
+ ///
+ /// \param SS The nested-name-specifier, which will be updated in-place
+ /// to reflect the parsed nested-name-specifier.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnMsSuperScopeSpecifier(Scope *S, SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc,
+ CXXScopeSpec &SS);
bool isAcceptableNestedNameSpecifier(const NamedDecl *SD);
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -4195,7 +4195,8 @@
}
case NestedNameSpecifier::Global:
- // The global specifier is canonical and unique.
+ case NestedNameSpecifier::MsSuper:
+ // The global specifier and __super specifer are canonical and unique.
return NNS;
}
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -4760,6 +4760,13 @@
case NestedNameSpecifier::Global:
return NestedNameSpecifier::GlobalSpecifier(ToContext);
+ case NestedNameSpecifier::MsSuper:
+ if (CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
+ return NestedNameSpecifier::MsSuperSpecifier(ToContext, RD);
+ }
+ return nullptr;
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
QualType T = Import(QualType(FromNNS->getAsType(), 0u));
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp
+++ lib/AST/ExprCXX.cpp
@@ -1399,7 +1399,8 @@
// It can't be dependent: after all, we were actually able to do the
// lookup.
CXXRecordDecl *Record = nullptr;
- if (getQualifier()) {
+ auto *NNS = getQualifier();
+ if (NNS && NNS->getKind() != NestedNameSpecifier::MsSuper) {
const Type *T = getQualifier()->getAsType();
assert(T && "qualifier in member expression does not name type");
Record = T->getAsCXXRecordDecl();
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -811,6 +811,9 @@
// We never want an 'E' here.
return;
+ case NestedNameSpecifier::MsSuper:
+ llvm_unreachable("Can't mangle __super specifier");
+
case NestedNameSpecifier::Namespace:
if (qualifier->getPrefix())
mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
@@ -1456,6 +1459,7 @@
void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
switch (qualifier->getKind()) {
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
// nothing
return;
Index: lib/AST/NestedNameSpecifier.cpp
===================================================================
--- lib/AST/NestedNameSpecifier.cpp
+++ lib/AST/NestedNameSpecifier.cpp
@@ -66,7 +66,7 @@
"Broken nested name specifier");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredNamespaceOrAlias);
+ Mockup.Prefix.setInt(StoredDecl);
Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
return FindOrInsert(Context, Mockup);
}
@@ -82,7 +82,7 @@
"Broken nested name specifier");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(StoredNamespaceOrAlias);
+ Mockup.Prefix.setInt(StoredDecl);
Mockup.Specifier = Alias;
return FindOrInsert(Context, Mockup);
}
@@ -118,17 +118,30 @@
return Context.GlobalNestedNameSpecifier;
}
+NestedNameSpecifier *
+NestedNameSpecifier::MsSuperSpecifier(const ASTContext &Context,
+ CXXRecordDecl *RD) {
+ NestedNameSpecifier Mockup;
+ Mockup.Prefix.setPointer(nullptr);
+ Mockup.Prefix.setInt(StoredDecl);
+ Mockup.Specifier = RD;
+ return FindOrInsert(Context, Mockup);
+}
+
NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
if (!Specifier)
return Global;
switch (Prefix.getInt()) {
case StoredIdentifier:
return Identifier;
- case StoredNamespaceOrAlias:
- return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace
- : NamespaceAlias;
+ case StoredDecl: {
+ NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
+ if (isa<CXXRecordDecl>(ND))
+ return MsSuper;
+ return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
+ }
case StoredTypeSpec:
return TypeSpec;
@@ -140,24 +153,29 @@
llvm_unreachable("Invalid NNS Kind!");
}
-/// \brief Retrieve the namespace stored in this nested name
-/// specifier.
+/// \brief Retrieve the namespace stored in this nested name specifier.
NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
- if (Prefix.getInt() == StoredNamespaceOrAlias)
+ if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
return nullptr;
}
-/// \brief Retrieve the namespace alias stored in this nested name
-/// specifier.
+/// \brief Retrieve the namespace alias stored in this nested name specifier.
NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
- if (Prefix.getInt() == StoredNamespaceOrAlias)
+ if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
return nullptr;
}
+/// \brief Retrieve the record declaration stored in this nested name specifier.
+CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
+ if (Prefix.getInt() == StoredDecl)
+ return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
+
+ return nullptr;
+}
/// \brief Whether this nested name specifier refers to a dependent
/// type or not.
@@ -172,6 +190,15 @@
case Global:
return false;
+ case MsSuper: {
+ CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
+ for (const auto &Base : RD->bases())
+ if (Base.getType()->isDependentType())
+ return true;
+
+ return false;
+ }
+
case TypeSpec:
case TypeSpecWithTemplate:
return getAsType()->isDependentType();
@@ -191,8 +218,9 @@
case Namespace:
case NamespaceAlias:
case Global:
+ case MsSuper:
return false;
-
+
case TypeSpec:
case TypeSpecWithTemplate:
return getAsType()->isInstantiationDependentType();
@@ -209,6 +237,7 @@
case Namespace:
case NamespaceAlias:
case Global:
+ case MsSuper:
return false;
case TypeSpec:
@@ -246,6 +275,10 @@
case Global:
break;
+ case MsSuper:
+ OS << "__super";
+ break;
+
case TypeSpecWithTemplate:
OS << "template ";
// Fall through to print the type.
@@ -304,6 +337,7 @@
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::MsSuper:
// The location of the identifier or namespace name.
Length += sizeof(unsigned);
break;
@@ -369,6 +403,7 @@
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::MsSuper:
return SourceRange(LoadSourceLocation(Data, Offset),
LoadSourceLocation(Data, Offset + sizeof(unsigned)));
@@ -552,6 +587,17 @@
SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
}
+void NestedNameSpecifierLocBuilder::MakeMsSuper(ASTContext &Context,
+ CXXRecordDecl *RD,
+ SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc) {
+ Representation = NestedNameSpecifier::MsSuperSpecifier(Context, RD);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+}
+
void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
NestedNameSpecifier *Qualifier,
SourceRange R) {
@@ -583,6 +629,7 @@
}
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
break;
}
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -2731,6 +2731,7 @@
goto DoneWithDeclSpec;
// typedef-name
+ case tok::kw___super:
case tok::kw_decltype:
case tok::identifier: {
// This identifier can only be a typedef name if we haven't already seen
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -493,6 +493,12 @@
if (TryConsumeToken(tok::kw_typename, TypenameLoc))
HasTypenameKeyword = true;
+ if (Tok.is(tok::kw___super)) {
+ Diag(Tok.getLocation(), diag::err_super_in_using_declaration);
+ SkipUntil(tok::semi);
+ return nullptr;
+ }
+
// Parse nested-name-specifier.
IdentifierInfo *LastII = nullptr;
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false,
@@ -2054,7 +2060,8 @@
// Access declarations.
bool MalformedTypeSpec = false;
if (!TemplateInfo.Kind &&
- (Tok.is(tok::identifier) || Tok.is(tok::coloncolon))) {
+ (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+ Tok.is(tok::kw___super))) {
if (TryAnnotateCXXScopeToken())
MalformedTypeSpec = true;
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -688,11 +688,12 @@
ConsumeToken();
break;
+ case tok::kw___super:
case tok::kw_decltype:
// Annotate the token and tail recurse.
if (TryAnnotateTypeOrScopeToken())
return ExprError();
- assert(Tok.isNot(tok::kw_decltype));
+ assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
case tok::identifier: { // primary-expression: identifier
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -226,6 +226,17 @@
HasScopeSpecifier = true;
}
+ if (Tok.is(tok::kw___super)) {
+ SourceLocation SuperLoc = ConsumeToken();
+ if (!Tok.is(tok::coloncolon)) {
+ Diag(Tok.getLocation(), diag::err_expected_coloncolon_after_super);
+ return true;
+ }
+
+ return Actions.ActOnMsSuperScopeSpecifier(getCurScope(), SuperLoc,
+ ConsumeToken(), SS);
+ }
+
bool CheckForDestructor = false;
if (MayBePseudoDestructor && *MayBePseudoDestructor) {
CheckForDestructor = true;
Index: lib/Parse/ParseTentative.cpp
===================================================================
--- lib/Parse/ParseTentative.cpp
+++ lib/Parse/ParseTentative.cpp
@@ -1181,6 +1181,7 @@
return TPResult::False;
}
// Fall through.
+ case tok::kw___super:
case tok::kw_decltype:
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -1482,10 +1482,11 @@
/// Note that this routine emits an error if you call it with ::new or ::delete
/// as the current tokens, so only call it in contexts where these are invalid.
bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
- assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
- || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)
- || Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id))
- && "Cannot be a type or scope token!");
+ assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+ Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) ||
+ Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) ||
+ Tok.is(tok::kw___super)) &&
+ "Cannot be a type or scope token!");
if (Tok.is(tok::kw_typename)) {
// MSVC lets you do stuff like:
@@ -1694,7 +1695,8 @@
"Call sites of this function should be guarded by checking for C++");
assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
(Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) ||
- Tok.is(tok::kw_decltype)) && "Cannot be a type or scope token!");
+ Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super)) &&
+ "Cannot be a type or scope token!");
CXXScopeSpec SS;
if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
Index: lib/Sema/DeclSpec.cpp
===================================================================
--- lib/Sema/DeclSpec.cpp
+++ lib/Sema/DeclSpec.cpp
@@ -113,6 +113,18 @@
"NestedNameSpecifierLoc range computation incorrect");
}
+void CXXScopeSpec::MakeMsSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc) {
+ Builder.MakeMsSuper(Context, RD, SuperLoc, ColonColonLoc);
+
+ Range.setBegin(SuperLoc);
+ Range.setEnd(ColonColonLoc);
+
+ assert(Range == Builder.getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
void CXXScopeSpec::MakeTrivial(ASTContext &Context,
NestedNameSpecifier *Qualifier, SourceRange R) {
Builder.MakeTrivial(Context, Qualifier, R);
Index: lib/Sema/SemaCXXScopeSpec.cpp
===================================================================
--- lib/Sema/SemaCXXScopeSpec.cpp
+++ lib/Sema/SemaCXXScopeSpec.cpp
@@ -148,6 +148,9 @@
case NestedNameSpecifier::Global:
return Context.getTranslationUnitDecl();
+
+ case NestedNameSpecifier::MsSuper:
+ return NNS->getAsRecordDecl();
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
@@ -246,6 +249,26 @@
return false;
}
+bool Sema::ActOnMsSuperScopeSpecifier(Scope *S, SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc,
+ CXXScopeSpec &SS) {
+ CXXRecordDecl *RD = nullptr;
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(S->getEntity()))
+ RD = MD->getParent();
+ else
+ RD = dyn_cast<CXXRecordDecl>(S->getEntity());
+
+ assert(RD && "Not inside method or class scope!");
+
+ if (RD->getNumBases() == 0) {
+ Diag(SuperLoc, diag::err_no_base_classes) << RD->getName();
+ return true;
+ }
+
+ SS.MakeMsSuper(Context, RD, SuperLoc, ColonColonLoc);
+ return false;
+}
+
/// \brief Determines whether the given declaration is an valid acceptable
/// result for name lookup of a nested-name-specifier.
bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
@@ -950,6 +973,7 @@
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::MsSuper:
// These are never namespace scopes.
return true;
}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -497,6 +497,9 @@
/// @endcode
bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) {
if (CurContext->isRecord()) {
+ if (SS->getScopeRep()->getKind() == NestedNameSpecifier::MsSuper)
+ return true;
+
const Type *Ty = SS->getScopeRep()->getAsType();
CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
@@ -698,7 +701,11 @@
}
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
- LookupParsedName(Result, S, &SS, !CurMethod);
+ NestedNameSpecifier *NNS = SS.getScopeRep();
+ if (NNS && NNS->getKind() == NestedNameSpecifier::MsSuper)
+ LookupInMsSuper(Result, NNS->getAsRecordDecl());
+ else
+ LookupParsedName(Result, S, &SS, !CurMethod);
// For unqualified lookup in a class template in MSVC mode, look into
// dependent base classes where the primary class template is known.
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -67,6 +67,7 @@
break;
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
llvm_unreachable("Nested name specifier is not a type for inheriting ctor");
@@ -354,6 +355,7 @@
return true;
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
return false;
Index: lib/Sema/SemaLookup.cpp
===================================================================
--- lib/Sema/SemaLookup.cpp
+++ lib/Sema/SemaLookup.cpp
@@ -1824,6 +1824,26 @@
return LookupName(R, S, AllowBuiltinCreation);
}
+/// \brief Perform qualified name lookup into all base classes of the given
+/// class.
+///
+/// \param R captures both the lookup criteria and any lookup results found.
+///
+/// \param Class The context in which qualified name lookup will
+/// search. Name lookup will search in all base classes merging the results.
+void Sema::LookupInMsSuper(LookupResult &R, CXXRecordDecl *Class) {
+ for (const auto &BaseSpec : Class->bases()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(
+ BaseSpec.getType()->castAs<RecordType>()->getDecl());
+ LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind());
+ Result.setBaseObjectType(Context.getRecordType(Class));
+ LookupQualifiedName(Result, RD);
+ for (auto *Decl : Result)
+ R.addDecl(Decl);
+ }
+
+ R.resolveKind();
+}
/// \brief Produce a diagnostic describing the ambiguity that resulted
/// from name lookup.
@@ -3296,6 +3316,7 @@
break;
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
return;
}
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -4127,6 +4127,7 @@
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
return false;
case NestedNameSpecifier::TypeSpec:
@@ -7900,7 +7901,11 @@
DeclarationName Name(&II);
LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
- LookupQualifiedName(Result, Ctx);
+ NestedNameSpecifier *NNS = SS.getScopeRep();
+ if (NNS->getKind() == NestedNameSpecifier::MsSuper)
+ LookupInMsSuper(Result, NNS->getAsRecordDecl());
+ else
+ LookupQualifiedName(Result, Ctx);
unsigned DiagID = 0;
Decl *Referenced = nullptr;
switch (Result.getResultKind()) {
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -3021,6 +3021,7 @@
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
llvm_unreachable("Nested-name-specifier must name a type");
case NestedNameSpecifier::TypeSpec:
@@ -3717,6 +3718,7 @@
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
llvm_unreachable("Nested-name-specifier must name a type");
}
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -3100,6 +3100,14 @@
SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc());
break;
+ case NestedNameSpecifier::MsSuper: {
+ CXXRecordDecl *RD =
+ cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
+ SourceLocation(), QNNS->getAsRecordDecl()));
+ SS.MakeMsSuper(SemaRef.Context, RD, Q.getBeginLoc(), Q.getEndLoc());
+ break;
+ }
+
case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -7907,6 +7907,12 @@
// No associated value, and there can't be a prefix.
break;
}
+
+ case NestedNameSpecifier::MsSuper: {
+ CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx);
+ NNS = NestedNameSpecifier::MsSuperSpecifier(Context, RD);
+ break;
+ }
}
Prev = NNS;
}
@@ -7963,9 +7969,16 @@
Builder.MakeGlobal(Context, ColonColonLoc);
break;
}
+
+ case NestedNameSpecifier::MsSuper: {
+ CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx);
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ Builder.MakeMsSuper(Context, RD, Range.getBegin(), Range.getEnd());
+ break;
+ }
}
}
-
+
return Builder.getWithLocInContext(Context);
}
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -5208,6 +5208,10 @@
case NestedNameSpecifier::Global:
// Don't need to write an associated value.
break;
+
+ case NestedNameSpecifier::MsSuper:
+ AddDeclRef(NNS->getAsRecordDecl(), Record);
+ break;
}
}
}
@@ -5257,6 +5261,11 @@
case NestedNameSpecifier::Global:
AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record);
break;
+
+ case NestedNameSpecifier::MsSuper:
+ AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl(), Record);
+ AddSourceRange(NNS.getLocalSourceRange(), Record);
+ break;
}
}
}
Index: test/SemaCXX/MicrosoftExtensions.cpp
===================================================================
--- test/SemaCXX/MicrosoftExtensions.cpp
+++ test/SemaCXX/MicrosoftExtensions.cpp
@@ -398,3 +398,123 @@
_Static_assert(__alignof(s1) == 8, "");
_Static_assert(__alignof(s2) == 4, "");
}
+
+namespace MsSuper {
+struct Errors {
+ using __super::foo; // expected-error {{__super cannot be used}}
+ __super::XXX x; // expected-error {{invalid use of '__super'}} expected-error {{expected}}
+};
+
+struct Base1 {
+ void foo(int) {}
+
+ typedef int XXX;
+};
+
+struct Derived : Base1 {
+ __super::XXX x;
+ typedef __super::XXX Type;
+
+ void foo(int i) {
+ __super::foo(i);
+ }
+};
+
+struct Base2 {
+ void foo(char) {}
+};
+
+struct MemberFunctionInMultipleBases : Base1, Base2 {
+ void foo() {
+ __super::foo('x');
+ }
+};
+
+struct Base3 {
+ void foo(int) {}
+ void foo(char) {}
+};
+
+struct OverloadedMemberFunction : Base3 {
+ void foo() {
+ __super::foo('x');
+ }
+};
+
+struct PointerToMember : Base1 {
+ template <void (Base1::*MP)(int)>
+ struct Wrapper {
+ static void bar() {}
+ };
+
+ static void baz();
+};
+
+void PointerToMember::baz() {
+ Wrapper<&__super::foo>::bar();
+}
+
+template <typename T>
+struct BaseTemplate {
+ typedef int XXX;
+
+ void foo() {}
+};
+
+struct DerivedFromKnownSpecialization : BaseTemplate<int> {
+ __super::XXX a;
+ typedef __super::XXX b;
+
+ void test() {
+ __super::XXX c;
+ typedef __super::XXX d;
+
+ __super::foo();
+ }
+};
+
+template <typename T>
+struct DerivedFromDependentBase : BaseTemplate<T> {
+ typename __super::XXX a;
+ typedef typename __super::XXX b;
+
+ __super::XXX c; // expected-error {{missing 'typename'}}
+ typedef __super::XXX d; // expected-error {{missing 'typename'}}
+
+ void test() {
+ typename __super::XXX e;
+ typedef typename __super::XXX f;
+
+ __super::XXX g; // expected-error {{missing 'typename'}}
+ typedef __super::XXX h; // expected-error {{missing 'typename'}}
+
+ __super::foo();
+ }
+};
+
+template <typename T>
+struct DerivedFromTemplateParameter : T {
+ typename __super::XXX a;
+ typedef typename __super::XXX b;
+
+ __super::XXX c; // expected-error {{missing 'typename'}}
+ typedef __super::XXX d; // expected-error {{missing 'typename'}}
+
+ void test() {
+ typename __super::XXX e;
+ typedef typename __super::XXX f;
+
+ __super::XXX g; // expected-error {{missing 'typename'}}
+ typedef __super::XXX h; // expected-error {{missing 'typename'}}
+
+ __super::foo(1);
+ }
+};
+
+void instantiate() {
+ DerivedFromDependentBase<int> d;
+ d.test();
+ DerivedFromTemplateParameter<Base1> t;
+ t.test();
+}
+}
Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1260,6 +1260,7 @@
case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::MsSuper:
break;
}
@@ -1301,6 +1302,7 @@
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::MsSuper:
break;
}
}
Index: tools/libclang/IndexTypeSourceInfo.cpp
===================================================================
--- tools/libclang/IndexTypeSourceInfo.cpp
+++ tools/libclang/IndexTypeSourceInfo.cpp
@@ -129,6 +129,7 @@
switch (NNS.getNestedNameSpecifier()->getKind()) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::MsSuper:
break;
case NestedNameSpecifier::Namespace:
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits