[cfe-commits] r145785 - in /cfe/trunk: include/clang/AST/NestedNameSpecifier.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/TokenKinds.def include/clang/Parse/Parser.h include/clang/Sema/Sema.h 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/SemaCXXScopeSpec.cpp test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp

David Blaikie dblaikie at gmail.com
Sat Dec 3 21:04:19 PST 2011


Author: dblaikie
Date: Sat Dec  3 23:04:18 2011
New Revision: 145785

URL: http://llvm.org/viewvc/llvm-project?rev=145785&view=rev
Log:
Support decltype in nested-name-specifiers.

Added:
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp
Modified:
    cfe/trunk/include/clang/AST/NestedNameSpecifier.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp

Modified: cfe/trunk/include/clang/AST/NestedNameSpecifier.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NestedNameSpecifier.h?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/NestedNameSpecifier.h (original)
+++ cfe/trunk/include/clang/AST/NestedNameSpecifier.h Sat Dec  3 23:04:18 2011
@@ -36,8 +36,9 @@
 /// namespaces. For example, "foo::" in "foo::x" is a nested name
 /// specifier. Nested name specifiers are made up of a sequence of
 /// specifiers, each of which can be a namespace, type, identifier
-/// (for dependent names), or the global specifier ('::', must be the
-/// first specifier).
+/// (for dependent names), decltype specifier, or the global specifier ('::').
+/// The last two specifiers can only appear at the start of a 
+/// nested-namespace-specifier.
 class NestedNameSpecifier : public llvm::FoldingSetNode {
 
   /// \brief Enumeration describing

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Dec  3 23:04:18 2011
@@ -3993,6 +3993,8 @@
   "conversion function from %0 to %1 invokes a deleted function">;
   
 def err_expected_class_or_namespace : Error<"expected a class or namespace">;
+def err_expected_class : Error<"%0 is not a class%select{ or namespace|, "
+  "namespace, or scoped enumeration}1">;
 def err_missing_qualified_for_redecl : Error<
   "must qualify the name %0 to declare %q1 in this scope">;
 def err_invalid_declarator_scope : Error<

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Sat Dec  3 23:04:18 2011
@@ -560,6 +560,8 @@
                          // function template specialization (not a type),
                          // e.g., "std::swap<int>"
 ANNOTATION(primary_expr) // annotation for a primary expression
+ANNOTATION(decltype)     // annotation for a decltype expression,
+                         // e.g., "decltype(foo.bar())"
 
 // Annotation for #pragma unused(...)
 // For each argument inside the parentheses the pragma handler will produce

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Dec  3 23:04:18 2011
@@ -1901,7 +1901,10 @@
 
 
   void ParseTypeofSpecifier(DeclSpec &DS);
-  void ParseDecltypeSpecifier(DeclSpec &DS);
+  SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
+  void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, 
+                                         SourceLocation StartLoc,
+                                         SourceLocation EndLoc);
   void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
   void ParseAtomicSpecifier(DeclSpec &DS);
 

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Dec  3 23:04:18 2011
@@ -3326,6 +3326,10 @@
                                    bool EnteringContext,
                                    CXXScopeSpec &SS);
 
+  bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
+                                           const DeclSpec &DS, 
+                                           SourceLocation ColonColonLoc);
+
   bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
                                  IdentifierInfo &Identifier,
                                  SourceLocation IdentifierLoc,

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Dec  3 23:04:18 2011
@@ -1889,6 +1889,7 @@
       goto DoneWithDeclSpec;
         
       // typedef-name
+    case tok::kw_decltype:
     case tok::identifier: {
       // In C++, check to see if this is a scope specifier like foo::bar::, if
       // so handle it as such.  This is important for ctor parsing.
@@ -2248,7 +2249,7 @@
       ParseTypeofSpecifier(DS);
       continue;
 
-    case tok::kw_decltype:
+    case tok::annot_decltype:
       ParseDecltypeSpecifier(DS);
       continue;
 
@@ -2370,6 +2371,7 @@
     if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
       break;
     // Fall through.
+  case tok::kw_decltype:
   case tok::kw_typename:  // typename foo::bar
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
@@ -2532,7 +2534,7 @@
     return true;
 
   // C++0x decltype support.
-  case tok::kw_decltype:
+  case tok::annot_decltype:
     ParseDecltypeSpecifier(DS);
     return true;
 
@@ -3346,6 +3348,7 @@
     if (TryAltiVecVectorToken())
       return true;
     // Fall through.
+  case tok::kw_decltype: // decltype(T())::type
   case tok::kw_typename: // typename T::type
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
@@ -3441,7 +3444,7 @@
     return true;
 
     // C++0x decltype.
-  case tok::kw_decltype:
+  case tok::annot_decltype:
     return true;
 
     // C1x _Atomic()
@@ -3968,6 +3971,10 @@
 
   while (1) {
     if (Tok.is(tok::l_paren)) {
+      // Enter function-declaration scope, limiting any declarators to the
+      // function prototype scope, including parameter declarators.
+      ParseScope PrototypeScope(this,
+                                Scope::FunctionPrototypeScope|Scope::DeclScope);
       // The paren may be part of a C++ direct initializer, eg. "int x(1);".
       // In such a case, check if we actually have a function declarator; if it
       // is not, the declarator has been fully parsed.
@@ -3982,13 +3989,14 @@
       BalancedDelimiterTracker T(*this, tok::l_paren);
       T.consumeOpen();
       ParseFunctionDeclarator(D, attrs, T);
+      PrototypeScope.Exit();
     } else if (Tok.is(tok::l_square)) {
       ParseBracketDeclarator(D);
     } else {
       break;
     }
   }
-}
+} 
 
 /// ParseParenDeclarator - We parsed the declarator D up to a paren.  This is
 /// only called before the identifier, so these are most likely just grouping
@@ -4084,7 +4092,12 @@
   // ParseFunctionDeclarator to handle of argument list.
   D.SetIdentifier(0, Tok.getLocation());
 
+  // Enter function-declaration scope, limiting any declarators to the
+  // function prototype scope, including parameter declarators.
+  ParseScope PrototypeScope(this,
+                            Scope::FunctionPrototypeScope|Scope::DeclScope);
   ParseFunctionDeclarator(D, attrs, T, RequiresArg);
+  PrototypeScope.Exit();
 }
 
 /// ParseFunctionDeclarator - We are after the identifier and have parsed the
@@ -4109,6 +4122,8 @@
                                      ParsedAttributes &attrs,
                                      BalancedDelimiterTracker &Tracker,
                                      bool RequiresArg) {
+  assert(getCurScope()->isFunctionPrototypeScope() && 
+         "Should call from a Function scope");
   // lparen is already consumed!
   assert(D.isPastIdentifier() && "Should not call before identifier!");
 
@@ -4142,11 +4157,6 @@
     Tracker.consumeClose();
     EndLoc = Tracker.getCloseLocation();
   } else {
-    // Enter function-declaration scope, limiting any declarators to the
-    // function prototype scope, including parameter declarators.
-    ParseScope PrototypeScope(this,
-                              Scope::FunctionPrototypeScope|Scope::DeclScope);
-
     if (Tok.isNot(tok::r_paren))
       ParseParameterDeclarationClause(D, attrs, ParamInfo, EllipsisLoc);
     else if (RequiresArg)
@@ -4197,9 +4207,6 @@
           EndLoc = Range.getEnd();
       }
     }
-
-    // Leave prototype scope.
-    PrototypeScope.Exit();
   }
 
   // Remember that we parsed a function type, and remember the attributes.

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Dec  3 23:04:18 2011
@@ -632,39 +632,85 @@
 ///
 /// 'decltype' ( expression )
 ///
-void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
-  assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier");
+SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
+  assert((Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))
+           && "Not a decltype specifier");
+  
 
-  SourceLocation StartLoc = ConsumeToken();
-  BalancedDelimiterTracker T(*this, tok::l_paren);
-  if (T.expectAndConsume(diag::err_expected_lparen_after,
-                       "decltype", tok::r_paren)) {
-    return;
-  }
+  ExprResult Result;
+  SourceLocation StartLoc = Tok.getLocation();
+  SourceLocation EndLoc;
 
-  // Parse the expression
+  if (Tok.is(tok::annot_decltype)) {
+    Result = getExprAnnotation(Tok);
+    EndLoc = Tok.getAnnotationEndLoc();
+    ConsumeToken();
+    if (Result.isInvalid()) {
+      DS.SetTypeSpecError();
+      return EndLoc;
+    }
+  } else {
+    ConsumeToken();
 
-  // C++0x [dcl.type.simple]p4:
-  //   The operand of the decltype specifier is an unevaluated operand.
-  EnterExpressionEvaluationContext Unevaluated(Actions,
-                                               Sema::Unevaluated);
-  ExprResult Result = ParseExpression();
-  if (Result.isInvalid()) {
-    SkipUntil(tok::r_paren);
-    return;
-  }
+    BalancedDelimiterTracker T(*this, tok::l_paren);
+    if (T.expectAndConsume(diag::err_expected_lparen_after,
+                           "decltype", tok::r_paren)) {
+      DS.SetTypeSpecError();
+      return T.getOpenLocation() == Tok.getLocation() ?
+             StartLoc : T.getOpenLocation();
+    }
 
-  // Match the ')'
-  T.consumeClose();
-  if (T.getCloseLocation().isInvalid())
-    return;
+    // Parse the expression
+
+    // C++0x [dcl.type.simple]p4:
+    //   The operand of the decltype specifier is an unevaluated operand.
+    EnterExpressionEvaluationContext Unevaluated(Actions,
+                                                 Sema::Unevaluated);
+    Result = ParseExpression();
+    if (Result.isInvalid()) {
+      SkipUntil(tok::r_paren, true, true);
+      DS.SetTypeSpecError();
+      return Tok.is(tok::eof) ? Tok.getLocation() : ConsumeParen();
+    }
+
+    // Match the ')'
+    T.consumeClose();
+    if (T.getCloseLocation().isInvalid()) {
+      DS.SetTypeSpecError();
+      // FIXME: this should return the location of the last token
+      //        that was consumed (by "consumeClose()")
+      return T.getCloseLocation();
+    }
+
+    EndLoc = T.getCloseLocation();
+  }
 
   const char *PrevSpec = 0;
   unsigned DiagID;
   // Check for duplicate type specifiers (e.g. "int decltype(a)").
   if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
-                         DiagID, Result.release()))
+                         DiagID, Result.release())) {
     Diag(StartLoc, DiagID) << PrevSpec;
+    DS.SetTypeSpecError();
+  }
+  return EndLoc;
+}
+
+void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec& DS, 
+                                               SourceLocation StartLoc,
+                                               SourceLocation EndLoc) {
+  // make sure we have a token we can turn into an annotation token
+  if (PP.isBacktrackEnabled())
+    PP.RevertCachedTokens(1);
+  else
+    PP.EnterToken(Tok);
+
+  Tok.setKind(tok::annot_decltype);
+  setExprAnnotation(Tok, DS.getTypeSpecType() == TST_decltype ? 
+                         DS.getRepAsExpr() : ExprResult());
+  Tok.setAnnotationEndLoc(EndLoc);
+  Tok.setLocation(StartLoc);
+  PP.AnnotateCachedTokens(Tok);
 }
 
 void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
@@ -727,14 +773,16 @@
   BaseLoc = Tok.getLocation();
 
   // Parse decltype-specifier
-  if (Tok.is(tok::kw_decltype)) {
+  // tok == kw_decltype is just error recovery, it can only happen when SS 
+  // isn't empty
+  if (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) {
     if (SS.isNotEmpty())
       Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype)
         << FixItHint::CreateRemoval(SS.getRange());
     // Fake up a Declarator to use with ActOnTypeName.
     DeclSpec DS(AttrFactory);
 
-    ParseDecltypeSpecifier(DS);    
+    ParseDecltypeSpecifier(DS);
     EndLocation = DS.getSourceRange().getEnd();
 
     Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sat Dec  3 23:04:18 2011
@@ -664,6 +664,7 @@
     ConsumeToken();
     break;
       
+  case tok::kw_decltype:
   case tok::identifier: {      // primary-expression: identifier
                                // unqualified-id: identifier
                                // constant: enumeration-constant

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sat Dec  3 23:04:18 2011
@@ -168,6 +168,22 @@
     *MayBePseudoDestructor = false;
   }
 
+  if (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) {
+    DeclSpec DS(AttrFactory);
+    SourceLocation DeclLoc = Tok.getLocation();
+    SourceLocation EndLoc  = ParseDecltypeSpecifier(DS);
+    if (Tok.isNot(tok::coloncolon)) {
+      AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc);
+      return false;
+    }
+    
+    SourceLocation CCLoc = ConsumeToken();
+    if (Actions.ActOnCXXNestedNameSpecifierDecltype(SS, DS, CCLoc))
+      SS.SetInvalid(SourceRange(DeclLoc, CCLoc));
+
+    HasScopeSpecifier = true;
+  }
+
   while (true) {
     if (HasScopeSpecifier) {
       // C++ [basic.lookup.classref]p5:

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Sat Dec  3 23:04:18 2011
@@ -706,7 +706,6 @@
   case tok::kw_wchar_t:
   case tok::kw_char16_t:
   case tok::kw_char32_t:
-  case tok::kw_decltype:
   case tok::kw___underlying_type:
   case tok::kw_thread_local:
   case tok::kw__Decimal32:
@@ -848,13 +847,14 @@
     if (Next.is(tok::kw_new) ||    // ::new
         Next.is(tok::kw_delete))   // ::delete
       return TPResult::False();
-
+  }
+    // Fall through.
+  case tok::kw_decltype:
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
       return TPResult::Error();
     return isCXXDeclarationSpecifier();
-  }
       
     // decl-specifier:
     //   storage-class-specifier
@@ -1030,7 +1030,7 @@
   }
 
   // C++0x decltype support.
-  case tok::kw_decltype:
+  case tok::annot_decltype:
     return TPResult::True();
 
   // C++0x type traits support

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sat Dec  3 23:04:18 2011
@@ -1202,8 +1202,8 @@
 /// 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)) &&
-         "Cannot be a type or scope token!");
+          || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)
+          || Tok.is(tok::kw_decltype)) && "Cannot be a type or scope token!");
 
   if (Tok.is(tok::kw_typename)) {
     // Parse a C++ typename-specifier, e.g., "typename T::type".
@@ -1382,8 +1382,8 @@
   assert(getLang().CPlusPlus &&
          "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)))&&
-         "Cannot be a type or scope token!");
+          (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) ||
+         Tok.is(tok::kw_decltype)) && "Cannot be a type or scope token!");
 
   CXXScopeSpec SS;
   if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Sat Dec  3 23:04:18 2011
@@ -676,6 +676,29 @@
                                      /*ScopeLookupResult=*/0, false);
 }
 
+bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
+                                               const DeclSpec &DS,
+                                               SourceLocation ColonColonLoc) {
+  if (SS.isInvalid() || DS.getTypeSpecType() == DeclSpec::TST_error)
+    return true;
+
+  assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
+
+  QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+  if (!T->isDependentType() && !T->getAs<TagType>()) {
+    Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class) 
+      << T << getLangOptions().CPlusPlus;
+    return true;
+  }
+
+  TypeLocBuilder TLB;
+  DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
+  DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc());
+  SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
+            ColonColonLoc);
+  return false;
+}
+
 /// IsInvalidUnlessNestedName - This method is used for error recovery
 /// purposes to determine whether the specified identifier is only valid as
 /// a nested name specifier, for example a namespace name.  It is

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp?rev=145785&r1=145784&r2=145785&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp Sat Dec  3 23:04:18 2011
@@ -2,8 +2,7 @@
 
 struct S {
   S *p = this; // ok
-  decltype(this) q; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} \
-                       expected-error {{C++ requires a type specifier for all declarations}}
+  decltype(this) q; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
 
   int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
   int sz = sizeof(this); // ok

Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp?rev=145785&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp Sat Dec  3 23:04:18 2011
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+struct global {
+};
+
+namespace PR10127 {
+  struct outer {
+    struct middle {
+      struct inner {
+        int func();
+        int i;
+      };
+      struct inner2 {
+      };
+      struct inner3 {
+      };
+      int mfunc();
+    };
+    typedef int td_int;
+  };
+
+  struct str {
+    operator decltype(outer::middle::inner()) ();
+    operator decltype(outer::middle())::inner2 ();
+    operator decltype(outer())::middle::inner3 ();
+    str(int (decltype(outer::middle::inner())::*n)(),
+             int (decltype(outer::middle())::inner::*o)(),
+             int (decltype(outer())::middle::inner::*p)());
+  };
+
+  int decltype(outer::middle())::inner::func() {
+    return 0;
+  }
+
+  decltype(outer::middle::inner()) a;
+  void scope() {
+    a.decltype(outer::middle())::mfunc(); // expected-error{{'PR10127::outer::middle::mfunc' is not a member of class 'decltype(outer::middle::inner())'}}
+    a.decltype(outer::middle::inner())::func();
+    a.decltype(outer::middle())::inner::func();
+    a.decltype(outer())::middle::inner::func();
+
+    a.decltype(outer())::middle::inner::~inner();
+
+    decltype(outer())::middle::inner().func();
+  }
+  decltype(outer::middle())::inner b;
+  decltype(outer())::middle::inner c;
+  decltype(outer())::fail d; // expected-error{{no type named 'fail' in 'PR10127::outer'}}
+  decltype(outer())::fail::inner e; // expected-error{{no member named 'fail' in 'PR10127::outer'}}
+  decltype()::fail f; // expected-error{{expected expression}}
+  decltype()::middle::fail g; // expected-error{{expected expression}}
+  
+  decltype(int()) h;
+  decltype(int())::PR10127::outer i; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}}
+  decltype(int())::global j; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}}
+  
+  outer::middle k = decltype(outer())::middle();
+  outer::middle::inner l = decltype(outer())::middle::inner();
+
+  template<typename T>
+  struct templ {
+    typename decltype(T())::middle::inner x; // expected-error{{type 'decltype(int())' (aka 'int') cannot be used prior to '::' because it has no members}}
+  };
+
+  template class templ<int>; // expected-note{{in instantiation of template class 'PR10127::templ<int>' requested here}}
+  template class templ<outer>;
+
+  enum class foo {
+    bar,
+    baz
+  };
+  
+  foo m = decltype(foo::bar)::baz;
+
+  enum E {
+  };
+  struct bar {
+    enum E : decltype(outer())::td_int(4);
+    enum F : decltype(outer())::td_int;
+    enum G : decltype; // expected-error{{expected '(' after 'decltype'}}
+  };
+}





More information about the cfe-commits mailing list