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; }
            ^

llvm-svn: 39257
This commit is contained in:
Chris Lattner
2007-01-21 22:37:37 +00:00
parent f61c8a805d
commit 99d3177103
5 changed files with 78 additions and 40 deletions

View File

@@ -30,11 +30,10 @@ Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
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 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
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 @@ Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
// 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 @@ Decl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, Decl *PrevDecl) {
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);
}

View File

@@ -30,11 +30,10 @@ Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
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 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
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 @@ Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
// 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 @@ Decl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, Decl *PrevDecl) {
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);
}

View File

@@ -35,13 +35,16 @@ private:
/// 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 @@ private:
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 @@ public:
/// 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 @@ public:
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 @@ public:
/// 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 @@ public:
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 @@ class FunctionDecl : public ObjectDecl {
/// 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; }

View File

@@ -419,6 +419,10 @@ DIAG(err_unexpected_typedef, ERROR,
"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'")

View File

@@ -113,6 +113,16 @@ public:
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.