mirror of
https://github.com/intel/llvm.git
synced 2026-02-04 20:00:11 +08:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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'")
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user