]> granicus.if.org Git - clang/commitdiff
Do not add enums to prototype scope in C++ modes.
authorPeter Collingbourne <peter@pcc.me.uk>
Sat, 22 Feb 2014 03:05:49 +0000 (03:05 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Sat, 22 Feb 2014 03:05:49 +0000 (03:05 +0000)
The language forbids defining enums in prototypes, so this check is normally
redundant, but if an enum is defined during template instantiation it should
not be added to the prototype scope.

While at it, clean up the code that deals with tag definitions in prototype
scope and expand the visibility warning to cover the case where an anonymous
enum is defined.

Differential Revision: http://llvm-reviews.chandlerc.com/D2742

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201927 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Parse/ParseDecl.cpp
lib/Sema/SemaDecl.cpp
test/Sema/decl-in-prototype.c
test/SemaTemplate/instantiate-enum.cpp

index 14eb7ad560c19ce6c2e36a1a296ebe9e19079e2f..7c920581db5e6ed6022be28cce95b760eb83d2d7 100644 (file)
@@ -1512,8 +1512,6 @@ public:
   void CheckVariableDeclarationType(VarDecl *NewVD);
   void CheckCompleteVariableDeclaration(VarDecl *var);
   void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
-  void ActOnStartFunctionDeclarator();
-  void ActOnEndFunctionDeclarator();
 
   NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                      TypeSourceInfo *TInfo,
index 20ac4df54468b4134627852c3448c6b779f16858..8efbc3db39e3c347b937689e248ce3da43faaf4c 100644 (file)
@@ -5069,7 +5069,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
   ParsedAttributes FnAttrs(AttrFactory);
   TypeResult TrailingReturnType;
 
-  Actions.ActOnStartFunctionDeclarator();
   /* LocalEndLoc is the end location for the local FunctionTypeLoc.
      EndLoc is the end location for the function declarator.
      They differ for trailing return types. */
@@ -5198,8 +5197,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
                                              StartLoc, LocalEndLoc, D,
                                              TrailingReturnType),
                 FnAttrs, EndLoc);
-
-  Actions.ActOnEndFunctionDeclarator();
 }
 
 /// isFunctionDeclaratorIdentifierList - This parameter list may have an
index 06d4500f77e1eeef506819f72cfc8dd00c80bf2a..8e1871037ccc107595dfd3aad920de1fef5df7fe 100644 (file)
@@ -1399,15 +1399,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
   }
 }
 
-void Sema::ActOnStartFunctionDeclarator() {
-  ++InFunctionDeclarator;
-}
-
-void Sema::ActOnEndFunctionDeclarator() {
-  assert(InFunctionDeclarator);
-  --InFunctionDeclarator;
-}
-
 /// \brief Look for an Objective-C class in the translation unit.
 ///
 /// \param Id The name of the Objective-C class we're looking for. If
@@ -11071,10 +11062,14 @@ CreateNewDecl:
   if (Attr)
     ProcessDeclAttributeList(S, New, Attr);
 
-  // If we're declaring or defining a tag in function prototype scope
-  // in C, note that this type can only be used within the function.
-  if (Name && S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus)
+  // If we're declaring or defining a tag in function prototype scope in C,
+  // note that this type can only be used within the function and add it to
+  // the list of decls to inject into the function definition scope.
+  if (!getLangOpts().CPlusPlus && (Name || Kind == TTK_Enum) &&
+      getNonFieldDeclScope(S)->isFunctionPrototypeScope()) {
     Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+    DeclsInPrototypeScope.push_back(New);
+  }
 
   // Set the lexical context. If the tag has a C++ scope specifier, the
   // lexical context will be different from the semantic context.
@@ -11124,12 +11119,6 @@ CreateNewDecl:
         II->isStr("FILE"))
       Context.setFILEDecl(New);
 
-  // If we were in function prototype scope (and not in C++ mode), add this
-  // tag to the list of decls to inject into the function definition scope.
-  if (S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus &&
-      InFunctionDeclarator && Name)
-    DeclsInPrototypeScope.push_back(New);
-
   if (PrevDecl)
     mergeDeclAttributes(New, PrevDecl);
 
@@ -12952,11 +12941,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
   Enum->completeDefinition(BestType, BestPromotionType,
                            NumPositiveBits, NumNegativeBits);
 
-  // If we're declaring a function, ensure this decl isn't forgotten about -
-  // it needs to go into the function scope.
-  if (InFunctionDeclarator)
-    DeclsInPrototypeScope.push_back(Enum);
-
   CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
 
   // Now that the enum type is defined, ensure it's not been underaligned.
index 877f887392422275acacd92e7a6f18a6f9af114f..9cb7fabab36c138733ed532d73bc605ee3593a1f 100644 (file)
@@ -2,11 +2,11 @@
 
 const int AA = 5;
 
-int f1(enum {AA,BB} E) {
+int f1(enum {AA,BB} E) { // expected-warning {{will not be visible outside of this function}}
     return BB;
 }
 
-int f2(enum {AA=7,BB} E) {
+int f2(enum {AA=7,BB} E) { // expected-warning {{will not be visible outside of this function}}
     return AA;
 }
 
index 5353a92a90bc85c503c762c9acbf79082e4c1471..3da8eb4a6c0a462ffc264cc94ad499d86de132a4 100644 (file)
@@ -25,3 +25,18 @@ namespace PR6375 {
 
   template void f<int>();
 }
+
+namespace EnumScoping {
+
+template <typename T>
+class C {
+  enum {
+    value = 42
+  };
+};
+
+void f(int i, C<int>::C c) {
+  int value;
+}
+
+}