Fingers crossed.

I'm not too happy with what I had to do with FileCheck to get the lambda test 
case working. This whole file expects c++11 to be disabled which prevents me 
from using -verify. I thought about moving this to MicrosoftCompatibility.cpp 
but that's misleading as __super is controlled by -mfs-extensions. Separate 
file for __super tests would be the way to solve all problems?

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/Scope.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::Super:
     return true;
 
   case NestedNameSpecifier::TypeSpec:
@@ -648,6 +649,7 @@
   case NestedNameSpecifier::Namespace:
   case NestedNameSpecifier::NamespaceAlias:
   case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Super:
     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.
+    Super
   };
 
 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 *SuperSpecifier(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 MakeSuper(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::Super:
     return true;
 
   case NestedNameSpecifier::TypeSpec:
@@ -714,6 +715,7 @@
   case NestedNameSpecifier::Namespace:
   case NestedNameSpecifier::NamespaceAlias:
   case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Super:
     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<
@@ -521,6 +523,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
@@ -527,6 +527,9 @@
           "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 err_invalid_super_scope : Error<"invalid use of '__super', "
+  "this keyword can only be used inside class or non-static member function scope">;
 
 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 MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
+                 SourceLocation SuperLoc, SourceLocation ColonColonLoc);
+
   /// \brief Make a new nested-name-specifier from incomplete source-location
   /// information.
   ///
Index: include/clang/Sema/Scope.h
===================================================================
--- include/clang/Sema/Scope.h
+++ include/clang/Sema/Scope.h
@@ -300,6 +300,9 @@
     return ErrorTrap.hasUnrecoverableErrorOccurred();
   }
 
+  /// isFunctionScope() - Return true if this scope is a function scope.
+  bool isFunctionScope() const { return (getFlags() & Scope::FnScope); }
+
   /// isClassScope - Return true if this scope is a class/struct/union scope.
   bool isClassScope() const {
     return (getFlags() & Scope::ClassScope);
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -2613,6 +2613,7 @@
   ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc,
                                    RedeclarationKind Redecl
                                      = NotForRedeclaration);
+  void LookupInSuper(LookupResult &R, CXXRecordDecl *Class);
 
   void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
                                     QualType T1, QualType T2,
@@ -4476,16 +4477,26 @@
 
   /// \brief The parser has parsed a global nested-name-specifier '::'.
   ///
-  /// \param S The scope in which this nested-name-specifier occurs.
-  ///
   /// \param CCLoc 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 ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
-                                    CXXScopeSpec &SS);
+  bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS);
+
+  /// \brief The parser has parsed a '__super' nested-name-specifier.
+  ///
+  /// \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 ActOnSuperScopeSpecifier(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::Super:
+    // 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::Super:
+    if (CXXRecordDecl *RD =
+            cast<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
+      return NestedNameSpecifier::SuperSpecifier(ToContext, RD);
+    }
+    return nullptr;
+
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate: {
       QualType T = Import(QualType(FromNNS->getAsType(), 0u));
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp
+++ lib/AST/ExprCXX.cpp
@@ -1404,7 +1404,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::Super) {
     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::Super:
+    llvm_unreachable("Can't mangle __super specifier");
+
   case NestedNameSpecifier::Namespace:
     if (qualifier->getPrefix())
       mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
@@ -1459,6 +1462,9 @@
     // nothing
     return;
 
+  case NestedNameSpecifier::Super:
+    llvm_unreachable("Can't mangle __super specifier");
+
   case NestedNameSpecifier::Namespace:
     mangleName(qualifier->getAsNamespace());
     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,6 +118,16 @@
   return Context.GlobalNestedNameSpecifier;
 }
 
+NestedNameSpecifier *
+NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
+                                    CXXRecordDecl *RD) {
+  NestedNameSpecifier Mockup;
+  Mockup.Prefix.setPointer(nullptr);
+  Mockup.Prefix.setInt(StoredDecl);
+  Mockup.Specifier = RD;
+  return FindOrInsert(Context, Mockup);
+}
+
 NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
   if (!Specifier)
     return Global;
@@ -126,9 +136,12 @@
   case StoredIdentifier:
     return Identifier;
 
-  case StoredNamespaceOrAlias:
-    return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace
-                                                            : NamespaceAlias;
+  case StoredDecl: {
+    NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
+    if (isa<CXXRecordDecl>(ND))
+      return Super;
+    return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
+  }
 
   case StoredTypeSpec:
     return TypeSpec;
@@ -140,24 +153,29 @@
   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 Super: {
+    CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
+    for (const auto &Base : RD->bases())
+      if (Base.getType()->isDependentType())
+        return true;
+
+    return false;
+  }
+
   case TypeSpec:
   case TypeSpecWithTemplate:
     return getAsType()->isDependentType();
@@ -191,8 +218,9 @@
   case Namespace:
   case NamespaceAlias:
   case Global:
+  case Super:
     return false;
-    
+
   case TypeSpec:
   case TypeSpecWithTemplate:
     return getAsType()->isInstantiationDependentType();
@@ -209,6 +237,7 @@
   case Namespace:
   case NamespaceAlias:
   case Global:
+  case Super:
     return false;
 
   case TypeSpec:
@@ -246,6 +275,10 @@
   case Global:
     break;
 
+  case Super:
+    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::Super:
     // 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::Super:
     return SourceRange(LoadSourceLocation(Data, Offset),
                        LoadSourceLocation(Data, Offset + sizeof(unsigned)));
 
@@ -552,6 +587,17 @@
   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
 }
 
+void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
+                                              CXXRecordDecl *RD,
+                                              SourceLocation SuperLoc,
+                                              SourceLocation ColonColonLoc) {
+  Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
+
+  // Push source-location info into the buffer.
+  SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+}
+
 void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 
                                                 NestedNameSpecifier *Qualifier, 
                                                 SourceRange R) {
@@ -583,6 +629,7 @@
       }
         
       case NestedNameSpecifier::Global:
+      case NestedNameSpecifier::Super:
         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
@@ -218,7 +218,7 @@
       return false;
 
     // '::' - Global scope qualifier.
-    if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS))
+    if (Actions.ActOnCXXGlobalScopeSpecifier(ConsumeToken(), SS))
       return true;
 
     CheckForLParenAfterColonColon();
@@ -226,6 +226,16 @@
     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.ActOnSuperScopeSpecifier(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::MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
+                             SourceLocation SuperLoc,
+                             SourceLocation ColonColonLoc) {
+  Builder.MakeSuper(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::Super:
+    return NNS->getAsRecordDecl();
   }
 
   llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
@@ -240,12 +243,43 @@
   return true;
 }
 
-bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+bool Sema::ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc,
                                         CXXScopeSpec &SS) {
   SS.MakeGlobal(Context, CCLoc);
   return false;
 }
 
+bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
+                                    SourceLocation ColonColonLoc,
+                                    CXXScopeSpec &SS) {
+  CXXRecordDecl *RD = nullptr;
+  for (Scope *S = getCurScope(); S; S = S->getParent()) {
+    if (S->isFunctionScope()) {
+      CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(S->getEntity());
+      if (MD && !MD->isStatic())
+        RD = MD->getParent();
+      break;
+    }
+    if (S->isClassScope()) {
+      RD = cast<CXXRecordDecl>(S->getEntity());
+      break;
+    }
+  }
+
+  if (!RD || RD->isLambda()) {
+    Diag(SuperLoc, diag::err_invalid_super_scope);
+    return true;
+  }
+
+  if (RD->getNumBases() == 0) {
+    Diag(SuperLoc, diag::err_no_base_classes) << RD->getName();
+    return true;
+  }
+
+  SS.MakeSuper(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) {
@@ -953,6 +987,7 @@
   case NestedNameSpecifier::Identifier:
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::Super:
     // These are never namespace scopes.
     return true;
   }
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -498,6 +498,9 @@
 /// @endcode
 bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) {
   if (CurContext->isRecord()) {
+    if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super)
+      return true;
+
     const Type *Ty = SS->getScopeRep()->getAsType();
 
     CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
@@ -699,7 +702,11 @@
   }
 
   LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
-  LookupParsedName(Result, S, &SS, !CurMethod);
+  NestedNameSpecifier *NNS = SS.getScopeRep();
+  if (NNS && NNS->getKind() == NestedNameSpecifier::Super)
+    LookupInSuper(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::Super:
   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::Super:
   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::LookupInSuper(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::Super:
     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::Super:
     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::Super)
+    LookupInSuper(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::Super:
           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::Super:
         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::Super: {
+      CXXRecordDecl *RD =
+          cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
+              SourceLocation(), QNNS->getAsRecordDecl()));
+      SS.MakeSuper(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
@@ -7927,6 +7927,12 @@
       // No associated value, and there can't be a prefix.
       break;
     }
+
+    case NestedNameSpecifier::Super: {
+      CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx);
+      NNS = NestedNameSpecifier::SuperSpecifier(Context, RD);
+      break;
+    }
     }
     Prev = NNS;
   }
@@ -7983,9 +7989,16 @@
       Builder.MakeGlobal(Context, ColonColonLoc);
       break;
     }
+
+    case NestedNameSpecifier::Super: {
+      CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx);
+      SourceRange Range = ReadSourceRange(F, Record, Idx);
+      Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd());
+      break;
+    }
     }
   }
-  
+
   return Builder.getWithLocInContext(Context);
 }
 
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -5245,6 +5245,10 @@
     case NestedNameSpecifier::Global:
       // Don't need to write an associated value.
       break;
+
+    case NestedNameSpecifier::Super:
+      AddDeclRef(NNS->getAsRecordDecl(), Record);
+      break;
     }
   }
 }
@@ -5294,6 +5298,11 @@
     case NestedNameSpecifier::Global:
       AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record);
       break;
+
+    case NestedNameSpecifier::Super:
+      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,147 @@
   _Static_assert(__alignof(s1) == 8, "");
   _Static_assert(__alignof(s2) == 4, "");
 }
+
+namespace Super {
+struct Errors {
+  using __super::foo; // expected-error {{'__super' cannot be used with a using declaration}}
+  __super::XXX x; // expected-error {{invalid use of '__super', Errors has no base classes}} expected-error {{expected}}
+
+  // expected-error@+4 {{C++ requires a type specifier for all declarations}}
+  // expected-warning@+3 {{empty parentheses interpreted as a function declaration}}
+  // expected-note@+2 {{replace parentheses with an initializer to declare a variable}}
+  static void foo() {
+    __super::foo(); // expected-error {{invalid use of '__super', this keyword}}
+  }
+
+  // expected-error@+4 {{C++ requires a type specifier for all declarations}}
+  // expected-warning@+3 {{empty parentheses interpreted as a function declaration}}
+  // expected-note@+2 {{replace parentheses with an initializer to declare a variable}}
+  void bar() {
+    auto a = [] { __super::foo(); }; // expected-error {{invalid use of '__super', this keyword}}
+  }
+};
+
+struct Base1 {
+  void foo(int) {}
+
+  typedef int XXX;
+};
+
+struct Derived : Base1 {
+  __super::XXX x;
+  typedef __super::XXX Type;
+
+  enum E {
+    X = sizeof(__super::XXX)
+  };
+
+  void foo(int i) {
+    __super::foo(i);
+  }
+};
+
+struct Outer {
+  struct Inner : Base1 {
+    static const int x = sizeof(__super::XXX);
+  };
+};
+
+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::Super:
     break;      
   }
   
@@ -1301,6 +1302,7 @@
         
     case NestedNameSpecifier::Global:
     case NestedNameSpecifier::Identifier:
+    case NestedNameSpecifier::Super:
       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::Super:
     break;
 
   case NestedNameSpecifier::Namespace:
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to