Refactor conflict handling code, no functionality change.
llvm-svn: 39322
diff --git a/clang/AST/SemaDecl.cpp b/clang/AST/SemaDecl.cpp
index f5c4334..d2b5cb8 100644
--- a/clang/AST/SemaDecl.cpp
+++ b/clang/AST/SemaDecl.cpp
@@ -74,10 +74,6 @@
// TODO: emit error on 'typedef int;'
// if (!DS.isMissingDeclaratorOk()) Diag(...);
- // TODO: Register 'struct foo;' with the type system as an opaque struct.
-
- // TODO: Check that we don't already have 'union foo;' or something else
- // that conflicts.
return 0;
}
@@ -95,34 +91,90 @@
return 0;
}
+/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name
+/// and scope as a previous declaration 'Old'. Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *Old) {
+ // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+ // TODO: This is totally simplistic. It should handle merging functions
+ // together etc, merging extern int X; int X; ...
+ Diag(New->getLocation(), diag::err_redefinition, New->getName());
+ Diag(Old->getLocation(), diag::err_previous_definition);
+ return New;
+}
+
+/// MergeFunctionDecl - We just parsed a function 'New' which has the same name
+/// and scope as a previous declaration 'Old'. Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, Decl *Old) {
+ // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+ // TODO: This is totally simplistic. It should handle merging functions
+ // together etc, merging extern int X; int X; ...
+ Diag(New->getLocation(), diag::err_redefinition, New->getName());
+ Diag(Old->getLocation(), diag::err_previous_definition);
+ return New;
+}
+
+/// MergeVarDecl - We just parsed a variable 'New' which has the same name
+/// and scope as a previous declaration 'Old'. Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *Old) {
+ // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+ // TODO: This is totally simplistic. It should handle merging functions
+ // together etc, merging extern int X; int X; ...
+ Diag(New->getLocation(), diag::err_redefinition, New->getName());
+ Diag(Old->getLocation(), diag::err_previous_definition);
+ return New;
+}
+
Action::DeclTy *
Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup) {
IdentifierInfo *II = D.getIdentifier();
- if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary)) {
- // 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);
- }
- }
-
+ // See if this is a redefinition of a variable in the same scope.
+ Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary);
+ if (!S->isDeclScope(PrevDecl))
+ PrevDecl = 0; // If in outer scope, it isn't the same thing.
+
Decl *New;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
- New = ParseTypedefDecl(S, D);
- if (!New) return 0;
+ TypedefDecl *NewTD = ParseTypedefDecl(S, D);
+ if (!NewTD) return 0;
+
+ // Merge the decl with the existing one if appropriate.
+ if (PrevDecl) {
+ NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
+ if (NewTD == 0) return 0;
+ }
+ New = NewTD;
} else if (D.isFunctionDeclarator()) {
TypeRef R = GetTypeForDeclarator(D, S);
if (R.isNull()) return 0;
- New = new FunctionDecl(D.getIdentifierLoc(), II, R);
+
+ FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R);
+
+ // Merge the decl with the existing one if appropriate.
+ if (PrevDecl) {
+ NewFD = MergeFunctionDecl(NewFD, PrevDecl);
+ if (NewFD == 0) return 0;
+ }
+ New = NewFD;
} else {
TypeRef R = GetTypeForDeclarator(D, S);
if (R.isNull()) return 0;
- New = new VarDecl(D.getIdentifierLoc(), II, R);
+ VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R);
+
+ // Merge the decl with the existing one if appropriate.
+ if (PrevDecl) {
+ NewVD = MergeVarDecl(NewVD, PrevDecl);
+ if (NewVD == 0) return 0;
+ }
+ New = NewVD;
}
@@ -259,7 +311,7 @@
}
-Decl *Sema::ParseTypedefDecl(Scope *S, Declarator &D) {
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D) {
assert(D.getIdentifier() && "Wrong callback for declspec withotu declarator");
TypeRef T = GetTypeForDeclarator(D, S);