diff --git a/clang/AST/SemaDecl.cpp b/clang/AST/SemaDecl.cpp index 329ce987e69b..ea4d22ce6ad1 100644 --- a/clang/AST/SemaDecl.cpp +++ b/clang/AST/SemaDecl.cpp @@ -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(*I); - Decl *D = II.getFETokenInfo(); + Decl *D = static_cast(*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(); - + 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(); + if (PrevDecl) { // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. } - VarDecl *New = new VarDecl(II, static_cast(PI.TypeInfo), PrevDecl); + VarDecl *New = new VarDecl(PI.IdentLoc, II, static_cast(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); } diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index 329ce987e69b..ea4d22ce6ad1 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -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(*I); - Decl *D = II.getFETokenInfo(); + Decl *D = static_cast(*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(); - + 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(); + if (PrevDecl) { // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. } - VarDecl *New = new VarDecl(II, static_cast(PI.TypeInfo), PrevDecl); + VarDecl *New = new VarDecl(PI.IdentLoc, II, static_cast(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); } diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 3436dfccde63..9756b4dfed2f 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -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; } diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 66ac1744b439..4c6082cdecb7 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -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'") diff --git a/clang/include/clang/Parse/Scope.h b/clang/include/clang/Parse/Scope.h index 63d108c95738..0b364f755758 100644 --- a/clang/include/clang/Parse/Scope.h +++ b/clang/include/clang/Parse/Scope.h @@ -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.