]> granicus.if.org Git - clang/commitdiff
[MSVC Compat] Try to treat an implicit, fixed enum as an unfixed enum
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 8 Oct 2015 10:04:46 +0000 (10:04 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 8 Oct 2015 10:04:46 +0000 (10:04 +0000)
consider the following:
enum E *p;
enum E { e };

The above snippet is not ANSI C because 'enum E' has not bee defined
when we are processing the declaration of 'p'; however, it is a popular
extension to make the above work.  This would fail using the Microsoft
enum semantics because the definition of 'E' would implicitly have a
fixed underlying type of 'int' which would trigger diagnostic messages
about a mismatch between the declaration and the definition.

Instead, treat fixed underlying types as not fixed for the purposes of
the diagnostic.

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

include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/Sema/bitfield.c
test/Sema/decl-in-prototype.c
test/SemaObjC/default-synthesize-1.m
test/SemaTemplate/instantiate-local-class.cpp

index 332f8eac44914411cf6a629132ffc7a2195c7e81..3f118e726820810e2861e3d6ccd8ae54359f50ac 100644 (file)
@@ -1984,7 +1984,9 @@ public:
                                       Expr *val);
   bool CheckEnumUnderlyingType(TypeSourceInfo *TI);
   bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
-                              QualType EnumUnderlyingTy, const EnumDecl *Prev);
+                              QualType EnumUnderlyingTy,
+                              bool EnumUnderlyingIsImplicit,
+                              const EnumDecl *Prev);
 
   /// Determine whether the body of an anonymous enumeration should be skipped.
   /// \param II The name of the first enumerator.
index fcc40955836eb97db41b4226000dc7de82c4d655..a12ff3a02e9e2cd8761b2b6d3761acba44bd86cb 100644 (file)
@@ -11454,9 +11454,9 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
 
 /// Check whether this is a valid redeclaration of a previous enumeration.
 /// \return true if the redeclaration was invalid.
-bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
-                                  QualType EnumUnderlyingTy,
-                                  const EnumDecl *Prev) {
+bool Sema::CheckEnumRedeclaration(
+    SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy,
+    bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) {
   bool IsFixed = !EnumUnderlyingTy.isNull();
 
   if (IsScoped != Prev->isScoped()) {
@@ -11478,6 +11478,10 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
           << Prev->getIntegerTypeRange();
       return true;
     }
+  } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) {
+    ;
+  } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) {
+    ;
   } else if (IsFixed != Prev->isFixed()) {
     Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
       << Prev->isFixed();
@@ -11747,6 +11751,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
   // this early, because it's needed to detect if this is an incompatible
   // redeclaration.
   llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
+  bool EnumUnderlyingIsImplicit = false;
 
   if (Kind == TTK_Enum) {
     if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
@@ -11772,6 +11777,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
       if (getLangOpts().MSVCCompat || TUK == TUK_Definition) {
         // Microsoft enums are always of int type.
         EnumUnderlying = Context.IntTy.getTypePtr();
+        EnumUnderlyingIsImplicit = true;
       }
     }
   }
@@ -12119,7 +12125,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
           // returning the previous declaration, unless this is a definition,
           // in which case we want the caller to bail out.
           if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
-                                     ScopedEnum, EnumUnderlyingTy, PrevEnum))
+                                     ScopedEnum, EnumUnderlyingTy,
+                                     EnumUnderlyingIsImplicit, PrevEnum))
             return TUK == TUK_Declaration ? PrevTagDecl : nullptr;
         }
 
index 029af186fdca3f078976ffa2dfea8121c9e0fe19..1789855c40f1a2bf8d39b3b1b27e6b5b4bc032df 100644 (file)
@@ -835,7 +835,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
         SemaRef.SubstType(TI->getType(), TemplateArgs,
                           UnderlyingLoc, DeclarationName());
       SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(),
-                                     DefnUnderlying, Enum);
+                                     DefnUnderlying,
+                                     /*EnumUnderlyingIsImplicit=*/false, Enum);
     }
   }
 
index 60a6fcf10a546ce70f8c256aed9b669b129002d8..ba8460d3f6c73aabac8548cfc1060a31c2c66b93 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify -std=c11 -Wno-unused-value
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c11 -Wno-unused-value
 
 enum e0; // expected-note{{forward declaration of 'enum e0'}}
 
index e185d19b544e3f254408c0d63dba49546d980bfe..4f581aa54e531dc68e5d6a365dcc1a6e005364c8 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple %ms_abi_triple -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
 
 const int AA = 5;
 
index aa92e4a3ffcda778bea216ed2ee5eb4af1cc46fc..731aa863e103a9b0a7e83734f076f19b05b35c34 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -Wobjc-missing-property-synthesis -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -fsyntax-only -Wobjc-missing-property-synthesis -verify -Wno-objc-root-class %s
 // rdar://11295716
 
 @interface NSObject 
index 7fdc6ce0c28eac61c226554b166cc500acc71814..c0ea6a0bc870bf9803a2266a2443e31a3923fe5a 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -verify -std=c++11 %s
-// RUN: %clang_cc1 -triple %itanium_abi_triple -verify -std=c++11 -fdelayed-template-parsing %s
+// RUN: %clang_cc1 -verify -std=c++11 %s
+// RUN: %clang_cc1 -verify -std=c++11 -fdelayed-template-parsing %s
 
 template<typename T>
 void f0() {