[cfe-commits] r39257 - in /cfe/cfe/trunk: AST/SemaDecl.cpp Sema/SemaDecl.cpp include/clang/AST/Decl.h include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Scope.h

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:42:03 PDT 2007


Author: sabre
Date: Wed Jul 11 11:42:03 2007
New Revision: 39257

URL: http://llvm.org/viewvc/llvm-project?rev=39257&view=rev
Log:
Change scopes to maintain decls, not identifiers.
Detect and emit errors when names are redefined in the same scope, e.g.
test/Parser/argument_redef.c, which now emits:

argument_redef.c:4:22: error: redefinition of 'A'
int foo(int A) { int A; }
                     ^
argument_redef.c:4:13: error: previous definition is here
int foo(int A) { int A; }
            ^

Modified:
    cfe/cfe/trunk/AST/SemaDecl.cpp
    cfe/cfe/trunk/Sema/SemaDecl.cpp
    cfe/cfe/trunk/include/clang/AST/Decl.h
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/cfe/trunk/include/clang/Parse/Scope.h

Modified: cfe/cfe/trunk/AST/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaDecl.cpp?rev=39257&r1=39256&r2=39257&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/AST/SemaDecl.cpp Wed Jul 11 11:42:03 2007
@@ -30,11 +30,10 @@
 void Sema::PopScope(SourceLocation Loc, Scope *S) {
   for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
        I != E; ++I) {
-    IdentifierInfo &II = *static_cast<IdentifierInfo*>(*I);
-    Decl *D = II.getFETokenInfo<Decl>();
+    Decl *D = static_cast<Decl*>(*I);
     assert(D && "This decl didn't get pushed??");
     
-    II.setFETokenInfo(D->getNext());
+    D->getIdentifier()->setFETokenInfo(D->getNext());
     
     // This will have to be revisited for C++: there we want to nest stuff in
     // namespace decls etc.  Even for C, we might want a top-level translation
@@ -69,19 +68,27 @@
   IdentifierInfo *II = D.getIdentifier();
   Decl *PrevDecl = 0;
   
-  if (II) {
+  if (II)
     PrevDecl = II->getFETokenInfo<Decl>();
-    
+  if (PrevDecl) {
     // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+    if (S->isDeclScope(PrevDecl)) {
+      // TODO: This is totally simplistic.  It should handle merging functions
+      // together etc, merging extern int X; int X; ...
+      Diag(D.getIdentifierLoc(), diag::err_redefinition, II->getName());
+      Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+    }
   }
   
   Decl *New;
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
     New = ParseTypedefDecl(S, D, PrevDecl);
   else if (D.isFunctionDeclarator())
-    New = new FunctionDecl(II, GetTypeForDeclarator(D, S), PrevDecl);
+    New = new FunctionDecl(D.getIdentifierLoc(), II, GetTypeForDeclarator(D, S),
+                           PrevDecl);
   else
-    New = new VarDecl(II, GetTypeForDeclarator(D, S), PrevDecl);
+    New = new VarDecl(D.getIdentifierLoc(), II, GetTypeForDeclarator(D, S),
+                      PrevDecl);
   
   if (!New) return 0;
   
@@ -90,7 +97,7 @@
   if (II) {
     // If PrevDecl includes conflicting name here, emit a diagnostic.
     II->setFETokenInfo(New);
-    S->AddDecl(II);
+    S->AddDecl(New);
   }
   
   // If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
@@ -109,19 +116,21 @@
   IdentifierInfo *II = PI.Ident;
   Decl *PrevDecl = 0;
   
-  if (II) {
+  if (II)
     PrevDecl = II->getFETokenInfo<Decl>();
+  if (PrevDecl) {
     
     // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
   }
   
-  VarDecl *New = new VarDecl(II, static_cast<Type*>(PI.TypeInfo), PrevDecl);
+  VarDecl *New = new VarDecl(PI.IdentLoc, II, static_cast<Type*>(PI.TypeInfo),
+                             PrevDecl);
   
   // If this has an identifier, add it to the scope stack.
   if (II) {
     // If PrevDecl includes conflicting name here, emit a diagnostic.
     II->setFETokenInfo(New);
-    FnScope->AddDecl(II);
+    FnScope->AddDecl(New);
   }
 
   return New;
@@ -168,7 +177,7 @@
   // no arguments, not a function that takes a single void argument.
   if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
       FTI.ArgInfo[0].TypeInfo == Context.VoidTy.getAsOpaquePtr()) {
-    
+    // empty arg list, don't push any params.
   } else {
     for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
       Params.push_back(ParseParamDeclarator(D.getTypeObject(0), i,FnBodyScope));
@@ -225,6 +234,6 @@
   TypeRef T = GetTypeForDeclarator(D, S);
   if (T.isNull()) return 0;
   
-  return new TypedefDecl(D.getIdentifier(), T, PrevDecl);
+  return new TypedefDecl(D.getIdentifierLoc(), D.getIdentifier(), T, PrevDecl);
 }
 

Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39257&r1=39256&r2=39257&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:42:03 2007
@@ -30,11 +30,10 @@
 void Sema::PopScope(SourceLocation Loc, Scope *S) {
   for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
        I != E; ++I) {
-    IdentifierInfo &II = *static_cast<IdentifierInfo*>(*I);
-    Decl *D = II.getFETokenInfo<Decl>();
+    Decl *D = static_cast<Decl*>(*I);
     assert(D && "This decl didn't get pushed??");
     
-    II.setFETokenInfo(D->getNext());
+    D->getIdentifier()->setFETokenInfo(D->getNext());
     
     // This will have to be revisited for C++: there we want to nest stuff in
     // namespace decls etc.  Even for C, we might want a top-level translation
@@ -69,19 +68,27 @@
   IdentifierInfo *II = D.getIdentifier();
   Decl *PrevDecl = 0;
   
-  if (II) {
+  if (II)
     PrevDecl = II->getFETokenInfo<Decl>();
-    
+  if (PrevDecl) {
     // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+    if (S->isDeclScope(PrevDecl)) {
+      // TODO: This is totally simplistic.  It should handle merging functions
+      // together etc, merging extern int X; int X; ...
+      Diag(D.getIdentifierLoc(), diag::err_redefinition, II->getName());
+      Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+    }
   }
   
   Decl *New;
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
     New = ParseTypedefDecl(S, D, PrevDecl);
   else if (D.isFunctionDeclarator())
-    New = new FunctionDecl(II, GetTypeForDeclarator(D, S), PrevDecl);
+    New = new FunctionDecl(D.getIdentifierLoc(), II, GetTypeForDeclarator(D, S),
+                           PrevDecl);
   else
-    New = new VarDecl(II, GetTypeForDeclarator(D, S), PrevDecl);
+    New = new VarDecl(D.getIdentifierLoc(), II, GetTypeForDeclarator(D, S),
+                      PrevDecl);
   
   if (!New) return 0;
   
@@ -90,7 +97,7 @@
   if (II) {
     // If PrevDecl includes conflicting name here, emit a diagnostic.
     II->setFETokenInfo(New);
-    S->AddDecl(II);
+    S->AddDecl(New);
   }
   
   // If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
@@ -109,19 +116,21 @@
   IdentifierInfo *II = PI.Ident;
   Decl *PrevDecl = 0;
   
-  if (II) {
+  if (II)
     PrevDecl = II->getFETokenInfo<Decl>();
+  if (PrevDecl) {
     
     // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
   }
   
-  VarDecl *New = new VarDecl(II, static_cast<Type*>(PI.TypeInfo), PrevDecl);
+  VarDecl *New = new VarDecl(PI.IdentLoc, II, static_cast<Type*>(PI.TypeInfo),
+                             PrevDecl);
   
   // If this has an identifier, add it to the scope stack.
   if (II) {
     // If PrevDecl includes conflicting name here, emit a diagnostic.
     II->setFETokenInfo(New);
-    FnScope->AddDecl(II);
+    FnScope->AddDecl(New);
   }
 
   return New;
@@ -168,7 +177,7 @@
   // no arguments, not a function that takes a single void argument.
   if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
       FTI.ArgInfo[0].TypeInfo == Context.VoidTy.getAsOpaquePtr()) {
-    
+    // empty arg list, don't push any params.
   } else {
     for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
       Params.push_back(ParseParamDeclarator(D.getTypeObject(0), i,FnBodyScope));
@@ -225,6 +234,6 @@
   TypeRef T = GetTypeForDeclarator(D, S);
   if (T.isNull()) return 0;
   
-  return new TypedefDecl(D.getIdentifier(), T, PrevDecl);
+  return new TypedefDecl(D.getIdentifierLoc(), D.getIdentifier(), T, PrevDecl);
 }
 

Modified: cfe/cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Decl.h?rev=39257&r1=39256&r2=39257&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Decl.h Wed Jul 11 11:42:03 2007
@@ -35,13 +35,16 @@
   /// DeclKind - This indicates which class this is.
   Kind DeclKind;
   
+  /// Loc - The location that this decl.
+  SourceLocation Loc;
+  
   /// Identifier - The identifier for this declaration (e.g. the name for the
   /// variable, the tag for a struct).
   IdentifierInfo *Identifier;
   
   /// Type.
   TypeRef DeclType;
-  
+
   /// When this decl is in scope while parsing, the Next field contains a
   /// pointer to the shadowed decl of the same name.  When the scope is popped,
   /// Decls are relinked onto a containing decl object.
@@ -49,11 +52,12 @@
   Decl *Next;
   
 public:
-  Decl(Kind DK, IdentifierInfo *Id, TypeRef T, Decl *next)
-    : DeclKind(DK), Identifier(Id), DeclType(T), Next(next) {}
+  Decl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T, Decl *next)
+    : DeclKind(DK), Loc(L), Identifier(Id), DeclType(T), Next(next) {}
   virtual ~Decl();
   
-  const IdentifierInfo *getIdentifier() const { return Identifier; }
+  IdentifierInfo *getIdentifier() const { return Identifier; }
+  SourceLocation getLocation() const { return Loc; }
   const char *getName() const;
   
   TypeRef getType() const { return DeclType; }
@@ -69,8 +73,8 @@
 /// Objective-C classes.
 class TypeDecl : public Decl {
 public:
-  TypeDecl(Kind DK, IdentifierInfo *Id, TypeRef T, Decl *Next)
-    : Decl(DK, Id, T, Next) {}
+  TypeDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T, Decl *Next)
+    : Decl(DK, L, Id, T, Next) {}
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == Typedef; }
@@ -80,8 +84,8 @@
 class TypedefDecl : public TypeDecl {
 public:
   // FIXME: Remove Declarator argument.
-  TypedefDecl(IdentifierInfo *Id, TypeRef T, Decl *Next)
-    : TypeDecl(Typedef, Id, T, Next) {}
+  TypedefDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T, Decl *Next)
+    : TypeDecl(Typedef, L, Id, T, Next) {}
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == Typedef; }
@@ -91,8 +95,9 @@
 /// ObjectDecl - ObjectDecl - Represents a declaration of a value.
 class ObjectDecl : public Decl {
 protected:
-  ObjectDecl(Kind DK, IdentifierInfo *Id, TypeRef T, Decl *Next)
-    : Decl(DK, Id, T, Next) {}
+  ObjectDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T,
+             Decl *Next)
+    : Decl(DK, L, Id, T, Next) {}
 public:
   
   // Implement isa/cast/dyncast/etc.
@@ -107,8 +112,8 @@
 class VarDecl : public ObjectDecl {
   // TODO: Initializer.
 public:
-  VarDecl(IdentifierInfo *Id, TypeRef T, Decl *Next)
-    : ObjectDecl(Variable, Id, T, Next) {}
+  VarDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T, Decl *Next)
+    : ObjectDecl(Variable, L, Id, T, Next) {}
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == Variable; }
@@ -130,8 +135,9 @@
   /// function.
   Decl *DeclChain;
 public:
-  FunctionDecl(IdentifierInfo *Id, TypeRef T, Decl *Next)
-    : ObjectDecl(Function, Id, T, Next), ParamInfo(0), Body(0), DeclChain(0) {}
+  FunctionDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T, Decl *Next)
+    : ObjectDecl(Function, L, Id, T, Next),
+      ParamInfo(0), Body(0), DeclChain(0) {}
   virtual ~FunctionDecl();
   
   Stmt *getBody() const { return Body; }

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39257&r1=39256&r2=39257&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:42:03 2007
@@ -419,6 +419,10 @@
      "unexpected type name '%s': expected expression")
 DIAG(err_undeclared_var_use, ERROR,
      "use of undeclared identifier '%s'")
+DIAG(err_redefinition, ERROR,
+     "redefinition of '%s'")
+DIAG(err_previous_definition, ERROR,
+     "previous definition is here")
 
 DIAG(warn_implicit_function_decl, WARNING,
      "implicit declaration of function '%s'")

Modified: cfe/cfe/trunk/include/clang/Parse/Scope.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/Scope.h?rev=39257&r1=39256&r2=39257&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Scope.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Scope.h Wed Jul 11 11:42:03 2007
@@ -113,6 +113,16 @@
     DeclsInScope.push_back(D);
   }
   
+  /// isDeclScope - Return true if this is the scope that the specified decl is
+  /// declared in.
+  bool isDeclScope(Action::DeclTy *D) {
+    // FIXME: this is bad.  We should use a SmallSet instead of a smallvector
+    // for DeclsInScope to handle scopes with thousands of variables!
+    for (unsigned i = 0, e = DeclsInScope.size(); i != e; ++i)
+      if (DeclsInScope[i] == D)
+        return true;
+    return false;
+  }
   
   
   /// Init - This is used by the parser to implement scope caching.





More information about the cfe-commits mailing list