Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -133,6 +133,7 @@ /// This set is managed by the NestedNameSpecifier class. mutable llvm::FoldingSet NestedNameSpecifiers; mutable NestedNameSpecifier *GlobalNestedNameSpecifier; + mutable NestedNameSpecifier *MsSuperNestedNameSpecifier; friend class NestedNameSpecifier; /// \brief A cache mapping from RecordDecls to ASTRecordLayouts. Index: include/clang/AST/DataRecursiveASTVisitor.h =================================================================== --- include/clang/AST/DataRecursiveASTVisitor.h +++ include/clang/AST/DataRecursiveASTVisitor.h @@ -623,6 +623,7 @@ case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::MsSuper: return true; case NestedNameSpecifier::TypeSpec: @@ -647,6 +648,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 @@ -67,6 +67,8 @@ /// specifier as encoded within the prefix. void* Specifier; + static char MsSuperSpecifierId; + public: /// \brief The kind of specifier that completes this nested name /// specifier. @@ -83,7 +85,9 @@ /// stored as a Type*. TypeSpecWithTemplate, /// \brief The global specifier '::'. There is no stored value. - Global + Global, + /// \brief The Microsoft's '__super' keyword. There is no stored value. + MsSuper }; private: @@ -143,6 +147,9 @@ /// scope. static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); + /// \brief Returns the nested name specifier representing the __super keyword. + static NestedNameSpecifier *MsSuperSpecifier(const ASTContext &Context); + /// \brief Return the prefix of this nested name specifier. /// /// The prefix contains all of the parts of the nested name @@ -422,6 +429,11 @@ /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + /// \brief Turn this (empty) nested-name-specifier into the Microsoft's + /// '__super' specifier. + void MakeMsSuper(ASTContext &Context, SourceLocation MsSuperLoc, + 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 @@ -689,6 +689,7 @@ case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::MsSuper: return true; case NestedNameSpecifier::TypeSpec: @@ -713,7 +714,8 @@ case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: - return true; + case NestedNameSpecifier::MsSuper: + return true; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: 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 @@ -141,6 +141,11 @@ /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + /// \brief Turn this (empty) nested-name-specifier into the Microsoft's + /// '__super' specifier. + void MakeMsSuper(ASTContext &Context, SourceLocation MsSuperLoc, + 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 @@ -2578,6 +2578,8 @@ bool AllowBuiltinCreation = false); bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup = false); + bool LookupInBaseClasses(LookupResult &R, CXXRecordDecl *LookupRec, + bool InUnqualifiedLookup = false); bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation = false, bool EnteringContext = false); @@ -3354,6 +3356,9 @@ CorrectionCandidateCallback *CCC = nullptr, bool IsInlineAsmIdentifier = false); + ExprResult ActOnMsSuperIdExpression(Scope *S, CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo); + void DecomposeUnqualifiedId(const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, DeclarationNameInfo &NameInfo, @@ -4447,6 +4452,9 @@ bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, CXXScopeSpec &SS); + bool ActOnCXXMsSuperScopeSpecifier(Scope *S, SourceLocation SuperLoc, + SourceLocation CCLoc, 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 @@ -730,6 +730,7 @@ DependentTemplateSpecializationTypes(this_()), SubstTemplateTemplateParmPacks(this_()), GlobalNestedNameSpecifier(nullptr), + MsSuperNestedNameSpecifier(nullptr), Int128Decl(nullptr), UInt128Decl(nullptr), Float128StubDecl(nullptr), BuiltinVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr), @@ -4190,7 +4191,8 @@ } case NestedNameSpecifier::Global: - // The global specifier is canonical and unique. + case NestedNameSpecifier::MsSuper: + // Both the global and the __super specifier are canonical and unique. return NNS; } Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -4760,6 +4760,9 @@ case NestedNameSpecifier::Global: return NestedNameSpecifier::GlobalSpecifier(ToContext); + case NestedNameSpecifier::MsSuper: + return NestedNameSpecifier::MsSuperSpecifier(ToContext); + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { QualType T = Import(QualType(FromNNS->getAsType(), 0u)); Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -801,6 +801,9 @@ // switch (qualifier->getKind()) { + case NestedNameSpecifier::MsSuper: + // nothing + return; case NestedNameSpecifier::Global: Out << "gs"; @@ -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 @@ -24,6 +24,8 @@ using namespace clang; +char NestedNameSpecifier::MsSuperSpecifierId; + NestedNameSpecifier * NestedNameSpecifier::FindOrInsert(const ASTContext &Context, const NestedNameSpecifier &Mockup) { @@ -118,10 +120,25 @@ return Context.GlobalNestedNameSpecifier; } +NestedNameSpecifier * +NestedNameSpecifier::MsSuperSpecifier(const ASTContext &Context) { + if (!Context.MsSuperNestedNameSpecifier) { + Context.MsSuperNestedNameSpecifier = + new (Context, llvm::alignOf()) + NestedNameSpecifier(); + Context.MsSuperNestedNameSpecifier->Specifier = &MsSuperSpecifierId; + } + + return Context.MsSuperNestedNameSpecifier; +} + NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { if (!Specifier) return Global; + if (Specifier == &MsSuperSpecifierId) + return MsSuper; + switch (Prefix.getInt()) { case StoredIdentifier: return Identifier; @@ -170,6 +187,7 @@ case Namespace: case NamespaceAlias: case Global: + case MsSuper: return false; case TypeSpec: @@ -191,6 +209,7 @@ case Namespace: case NamespaceAlias: case Global: + case MsSuper: return false; case TypeSpec: @@ -209,6 +228,7 @@ case Namespace: case NamespaceAlias: case Global: + case MsSuper: return false; case TypeSpec: @@ -246,6 +266,10 @@ case Global: break; + case MsSuper: + OS << "__super"; + break; + case TypeSpecWithTemplate: OS << "template "; // Fall through to print the type. @@ -304,6 +328,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 +394,7 @@ case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::MsSuper: return SourceRange(LoadSourceLocation(Data, Offset), LoadSourceLocation(Data, Offset + sizeof(unsigned))); @@ -556,6 +582,17 @@ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); } +void NestedNameSpecifierLocBuilder::MakeMsSuper(ASTContext &Context, + SourceLocation MsSuperLoc, + SourceLocation ColonColonLoc) { + assert(!Representation && "Already have a nested-name-specifier!?"); + Representation = NestedNameSpecifier::MsSuperSpecifier(Context); + + // Push source-location info into the buffer. + SaveSourceLocation(MsSuperLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); +} + void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R) { @@ -573,6 +610,7 @@ case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::MsSuper: SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); break; Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -695,6 +695,7 @@ assert(Tok.isNot(tok::kw_decltype)); return ParseCastExpression(isUnaryExpression, isAddressOfOperand); + case tok::kw___super: case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -224,6 +224,16 @@ CheckForLParenAfterColonColon(); HasScopeSpecifier = true; + } else if (Tok.is(tok::kw___super)) { + SourceLocation SuperLoc = ConsumeToken(); + if (Tok.isNot(tok::coloncolon)) { + // XXX: Diagnose + return true; + } + if (Actions.ActOnCXXMsSuperScopeSpecifier(getCurScope(), SuperLoc, + ConsumeToken(), SS)) + return true; + HasScopeSpecifier = true; } bool CheckForDestructor = false; Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -1484,7 +1484,8 @@ 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)) + || 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)) { Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -113,6 +113,17 @@ "NestedNameSpecifierLoc range computation incorrect"); } +void CXXScopeSpec::MakeMsSuper(ASTContext &Context, SourceLocation MsSuperLoc, + SourceLocation ColonColonLoc) { + Builder.MakeMsSuper(Context, MsSuperLoc, ColonColonLoc); + + Range.setBegin(MsSuperLoc); + 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,11 +148,21 @@ case NestedNameSpecifier::Global: return Context.getTranslationUnitDecl(); + + case NestedNameSpecifier::MsSuper: + return nullptr; } llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } +bool Sema::ActOnCXXMsSuperScopeSpecifier(Scope *S, SourceLocation SuperLoc, + SourceLocation CCLoc, + CXXScopeSpec &SS) { + SS.MakeMsSuper(Context, SuperLoc, CCLoc); + return false; +} + bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { if (!SS.isSet() || SS.isInvalid()) return false; @@ -936,6 +946,7 @@ switch (Qualifier->getKind()) { case NestedNameSpecifier::Global: + case NestedNameSpecifier::MsSuper: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: // These are always namespace scopes. We never want to enter a Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -1943,6 +1943,24 @@ return true; } +ExprResult Sema::ActOnMsSuperIdExpression(Scope *S, CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo) { + Scope *FnScope = S->getFnParent(); + CXXMethodDecl *Method = dyn_cast(FnScope->getEntity()); + CXXRecordDecl *Rec = Method->getParent(); + LookupResult R(*this, NameInfo, LookupOrdinaryName); + if (LookupInBaseClasses(R, Rec)) { + // if (R.getAmbiguityKind() == LookupResult::AmbiguousBaseSubobjectTypes) { + // Do overload resolution? + // } + + return BuildImplicitMemberExpr(SS, SourceLocation(), R, nullptr, true); + } + + Diag(R.getNameLoc(), diag::err_no_member) << R.getLookupName() << Rec; + return ExprError(); +} + /// In Microsoft mode, if we are inside a template class whose parent class has /// dependent base classes, and we can't resolve an unqualified identifier, then /// assume the identifier is a member of a dependent base class. We can only @@ -2010,6 +2028,10 @@ const TemplateArgumentListInfo *TemplateArgs; DecomposeUnqualifiedId(Id, TemplateArgsBuffer, NameInfo, TemplateArgs); + const NestedNameSpecifier *NNS = SS.getScopeRep(); + if (NNS && NNS->getKind() == NestedNameSpecifier::MsSuper) + return ActOnMsSuperIdExpression(S, SS, NameInfo); + DeclarationName Name = NameInfo.getName(); IdentifierInfo *II = Name.getAsIdentifierInfo(); SourceLocation NameLoc = NameInfo.getLoc(); @@ -2506,7 +2528,8 @@ // x = 17; // error: ambiguous base subobjects // Derived1::x = 17; // okay, pick the Base subobject of Derived1 // } - if (Qualifier && Qualifier->getAsType()) { + if (Qualifier && Qualifier->getAsType() && + Qualifier->getKind() != NestedNameSpecifier::MsSuper) { QualType QType = QualType(Qualifier->getAsType(), 0); assert(QType->isRecordType() && "lookup done with non-record type"); Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -69,6 +69,7 @@ case NestedNameSpecifier::Global: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::MsSuper: llvm_unreachable("Nested name specifier is not a type for inheriting ctor"); } @@ -356,6 +357,7 @@ case NestedNameSpecifier::Global: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::MsSuper: return false; } Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -1638,6 +1638,11 @@ if (!LookupRec || !LookupRec->getDefinition()) return false; + return LookupInBaseClasses(R, LookupRec, InUnqualifiedLookup); +} + +bool Sema::LookupInBaseClasses(LookupResult &R, CXXRecordDecl *LookupRec, + bool InUnqualifiedLookup) { // If we're performing qualified name lookup into a dependent class, // then we are actually looking into a current instantiation. If we have any // dependent base classes, then we either have to delay lookup until @@ -3314,6 +3319,7 @@ break; case NestedNameSpecifier::Global: + case NestedNameSpecifier::MsSuper: return; } Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -4124,6 +4124,7 @@ case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::MsSuper: return false; case NestedNameSpecifier::TypeSpec: Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -3019,6 +3019,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: @@ -3715,6 +3716,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 @@ -3064,6 +3064,12 @@ SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc()); break; + case NestedNameSpecifier::MsSuper: + // There is no meaningful transformation that one could perform on the + // __super specifier. + SS.MakeMsSuper(SemaRef.Context, 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 @@ -7800,6 +7800,12 @@ // No associated value, and there can't be a prefix. break; } + + case NestedNameSpecifier::MsSuper: { + NNS = NestedNameSpecifier::MsSuperSpecifier(Context); + break; + } + } Prev = NNS; } @@ -7856,6 +7862,13 @@ Builder.MakeGlobal(Context, ColonColonLoc); break; } + + case NestedNameSpecifier::MsSuper: { + SourceRange Range = ReadSourceRange(F, Record, Idx); + Builder.MakeMsSuper(Context, Range.getBegin(), Range.getEnd()); + break; + } + } } Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -5048,6 +5048,7 @@ break; case NestedNameSpecifier::Global: + case NestedNameSpecifier::MsSuper: // Don't need to write an associated value. break; } @@ -5097,6 +5098,7 @@ break; case NestedNameSpecifier::Global: + case NestedNameSpecifier::MsSuper: AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); break; } Index: test/SemaCXX/MicrosoftExtensions.cpp =================================================================== --- test/SemaCXX/MicrosoftExtensions.cpp +++ test/SemaCXX/MicrosoftExtensions.cpp @@ -421,3 +421,24 @@ _Static_assert(__alignof(s1) == 8, ""); _Static_assert(__alignof(s2) == 4, ""); } + +namespace super { +struct A { + void foo(int) {} +}; + +struct B { + void foo(char) {} +}; + +struct C : A { + void foo(int i) { + __super::foo(i); + } +}; + +struct D : A, B { + void foo() { + __super::foo('x'); + } +} Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -1256,6 +1256,7 @@ case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::Global: case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::MsSuper: break; } @@ -1297,6 +1298,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: