[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