aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp143
1 files changed, 84 insertions, 59 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a47094ecfe..3960a7d57c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -364,11 +364,13 @@ NamespaceDecl *Sema::GetStdNamespace() {
return StdNamespace;
}
-/// 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.
+/// 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. Returns true if there was an error,
+/// false otherwise.
///
-TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
+bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
bool objc_types = false;
// Allow multiple definitions for ObjC built-in typedefs.
// FIXME: Verify the underlying types are equivalent!
@@ -387,19 +389,19 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
break;
Context.setObjCClassType(New);
objc_types = true;
- return New;
+ return false;
case 3:
if (!TypeID->isStr("SEL"))
break;
Context.setObjCSelType(New);
objc_types = true;
- return New;
+ return false;
case 8:
if (!TypeID->isStr("Protocol"))
break;
Context.setObjCProtoType(New->getUnderlyingType());
objc_types = true;
- return New;
+ return false;
}
// Fall through - the typedef name was not a builtin type.
}
@@ -410,7 +412,7 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
<< New->getDeclName();
if (!objc_types)
Diag(OldD->getLocation(), diag::note_previous_definition);
- return New;
+ return true;
}
// Determine the "old" type we'll use for checking and diagnostics.
@@ -430,17 +432,17 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
<< New->getUnderlyingType() << OldType;
if (!objc_types)
Diag(Old->getLocation(), diag::note_previous_definition);
- return New;
+ return true;
}
- if (objc_types) return New;
- if (getLangOptions().Microsoft) return New;
+ if (objc_types) return false;
+ if (getLangOptions().Microsoft) return false;
// C++ [dcl.typedef]p2:
// In a given non-class scope, a typedef specifier can be used to
// redefine the name of any type declared in that scope to refer
// to the type to which it already refers.
if (getLangOptions().CPlusPlus && !isa<CXXRecordDecl>(CurContext))
- return New;
+ return false;
// In C, redeclaration of a type is a constraint violation (6.7.2.3p1).
// Apparently GCC, Intel, and Sun all silently ignore the redeclaration if
@@ -450,14 +452,14 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
if (PP.getDiagnostics().getSuppressSystemWarnings()) {
SourceManager &SrcMgr = Context.getSourceManager();
if (SrcMgr.isInSystemHeader(Old->getLocation()))
- return New;
+ return false;
if (SrcMgr.isInSystemHeader(New->getLocation()))
- return New;
+ return false;
}
Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return New;
+ return true;
}
/// DeclhasAttr - returns true if decl Declaration already has the target
@@ -494,25 +496,24 @@ static void MergeAttributes(Decl *New, Decl *Old) {
/// declarator D 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.
-/// Redeclaration will be set true if this New is a redeclaration OldD.
///
/// In C++, New and Old must be declarations that are not
/// overloaded. Use IsOverload to determine whether New and Old are
/// overloaded, and to select the Old declaration that New should be
/// merged with.
-FunctionDecl *
-Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
+///
+/// Returns true if there was an error, false otherwise.
+bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
assert(!isa<OverloadedFunctionDecl>(OldD) &&
"Cannot merge with an overloaded function declaration");
- Redeclaration = false;
// Verify the old decl was also a function.
FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD);
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
Diag(OldD->getLocation(), diag::note_previous_definition);
- return New;
+ return true;
}
// Determine whether the previous declaration was a definition,
@@ -520,12 +521,9 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
diag::kind PrevDiag;
if (Old->isThisDeclarationADefinition())
PrevDiag = diag::note_previous_definition;
- else if (Old->isImplicit()) {
- if (Old->getBuiltinID(Context))
- PrevDiag = diag::note_previous_builtin_declaration;
- else
- PrevDiag = diag::note_previous_implicit_declaration;
- } else
+ else if (Old->isImplicit())
+ PrevDiag = diag::note_previous_implicit_declaration;
+ else
PrevDiag = diag::note_previous_declaration;
QualType OldQType = Context.getCanonicalType(Old->getType());
@@ -543,8 +541,7 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
if (OldReturnType != NewReturnType) {
Diag(New->getLocation(), diag::err_ovl_diff_return_type);
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
- Redeclaration = true;
- return New;
+ return true;
}
const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
@@ -556,7 +553,7 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
if (OldMethod->isStatic() || NewMethod->isStatic()) {
Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
- return New;
+ return true;
}
// C++ [class.mem]p1:
@@ -586,7 +583,6 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
if (OldQType == NewQType) {
// We have a redeclaration.
MergeAttributes(New, Old);
- Redeclaration = true;
return MergeCXXFunctionDecl(New, Old);
}
@@ -598,19 +594,30 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
if (!getLangOptions().CPlusPlus &&
Context.typesAreCompatible(OldQType, NewQType)) {
MergeAttributes(New, Old);
- Redeclaration = true;
- return New;
+ return false;
}
// A function that has already been declared has been redeclared or defined
// with a different type- show appropriate diagnostic
+ if (unsigned BuiltinID = Old->getBuiltinID(Context)) {
+ // The user has declared a builtin function with an incompatible
+ // signature.
+ if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
+ // The function the user is redeclaring is a library-defined
+ // function like 'malloc' or 'printf'. Warn about the
+ // redeclaration, then ignore it.
+ Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
+ Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+ << Old << Old->getType();
+ return false;
+ }
+
+ PrevDiag = diag::note_previous_builtin_declaration;
+ }
- // 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_conflicting_types) << New->getDeclName();
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
- return New;
+ return true;
}
/// Predicate for C "tentative" external object definitions (C99 6.9.2).
@@ -671,14 +678,14 @@ void Sema::CheckForFileScopedRedefinitions(Scope *S, VarDecl *VD) {
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
/// definitions here, since the initializer hasn't been attached.
///
-VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
+bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
// Verify the old decl was also a variable.
VarDecl *Old = dyn_cast<VarDecl>(OldD);
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
Diag(OldD->getLocation(), diag::note_previous_definition);
- return New;
+ return true;
}
MergeAttributes(New, Old);
@@ -689,7 +696,7 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
Diag(New->getLocation(), diag::err_redefinition_different_type)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return New;
+ return true;
}
New->setType(MergedT);
// C99 6.2.2p4: Check if we have a static decl followed by a non-static.
@@ -698,21 +705,22 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
Old->getStorageClass() == VarDecl::Extern)) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return New;
+ return true;
}
// C99 6.2.2p4: Check if we have a non-static decl followed by a static.
if (New->getStorageClass() != VarDecl::Static &&
Old->getStorageClass() == VarDecl::Static) {
Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return New;
+ return true;
}
// Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
if (New->getStorageClass() != VarDecl::Extern && !New->isFileVarDecl()) {
Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
+ return true;
}
- return New;
+ return false;
}
/// CheckParmsForFunctionDef - Check that the parameters of the given
@@ -1245,7 +1253,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
NamedDecl *PrevDecl;
NamedDecl *New;
bool InvalidDecl = false;
-
+
// See if this is a redefinition of a variable in the same scope.
if (!D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid()) {
DC = CurContext;
@@ -1315,15 +1323,17 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
QualType R = GetTypeForDeclarator(D, S);
assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
+ bool Redeclaration = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
New = ActOnTypedefDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
- InvalidDecl);
+ InvalidDecl, Redeclaration);
} else if (R.getTypePtr()->isFunctionType()) {
New = ActOnFunctionDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
- IsFunctionDefinition, InvalidDecl);
+ IsFunctionDefinition, InvalidDecl,
+ Redeclaration);
} else {
New = ActOnVariableDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
- InvalidDecl);
+ InvalidDecl, Redeclaration);
}
if (New == 0)
@@ -1333,8 +1343,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
// lexical context will be different from the semantic context.
New->setLexicalDeclContext(CurContext);
- // If this has an identifier, add it to the scope stack.
- if (Name)
+ // If this has an identifier and is not an invalid redeclaration,
+ // add it to the scope stack.
+ if (Name && !(Redeclaration && InvalidDecl))
PushOnScopeChains(New, S);
// If any semantic error occurred, mark the decl as invalid.
if (D.getInvalidType() || InvalidDecl)
@@ -1346,7 +1357,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
NamedDecl*
Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, Decl* LastDeclarator,
- Decl* PrevDecl, bool& InvalidDecl) {
+ Decl* PrevDecl, bool& InvalidDecl,
+ bool &Redeclaration) {
// Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
@@ -1368,8 +1380,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
- NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
- if (NewTD == 0) return 0;
+ Redeclaration = true;
+ if (MergeTypeDefDecl(NewTD, PrevDecl))
+ InvalidDecl = true;
}
if (S->getFnParent() == 0) {
@@ -1390,7 +1403,8 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NamedDecl*
Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, Decl* LastDeclarator,
- Decl* PrevDecl, bool& InvalidDecl) {
+ Decl* PrevDecl, bool& InvalidDecl,
+ bool &Redeclaration) {
DeclarationName Name = GetNameForDeclarator(D);
// Check that there are no default arguments (C++ only).
@@ -1483,8 +1497,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
return 0;
}
- NewVD = MergeVarDecl(NewVD, PrevDecl);
- if (NewVD == 0) return 0;
+ Redeclaration = true;
+ if (MergeVarDecl(NewVD, PrevDecl))
+ InvalidDecl = true;
if (D.getCXXScopeSpec().isSet()) {
// No previous declaration in the qualifying scope.
@@ -1500,7 +1515,7 @@ NamedDecl*
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, Decl *LastDeclarator,
Decl* PrevDecl, bool IsFunctionDefinition,
- bool& InvalidDecl) {
+ bool& InvalidDecl, bool &Redeclaration) {
assert(R.getTypePtr()->isFunctionType());
DeclarationName Name = GetNameForDeclarator(D);
@@ -1691,7 +1706,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Merge the decl with the existing one if appropriate. Since C functions
// are in a flat namespace, make sure we consider decls in outer scopes.
bool OverloadableAttrRequired = false;
- bool Redeclaration = false;
if (PrevDecl &&
(!getLangOptions().CPlusPlus||isDeclInScope(PrevDecl, DC, S))) {
// Determine whether NewFD is an overload of PrevDecl or
@@ -1706,6 +1720,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (!AllowOverloadingOfFunction(PrevDecl, Context) ||
!IsOverload(NewFD, PrevDecl, MatchedDecl)) {
+ Redeclaration = true;
Decl *OldDecl = PrevDecl;
// If PrevDecl was an overloaded function, extract the
@@ -1715,10 +1730,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// NewFD and PrevDecl represent declarations that need to be
// merged.
- NewFD = MergeFunctionDecl(NewFD, OldDecl, Redeclaration);
+ if (MergeFunctionDecl(NewFD, OldDecl))
+ InvalidDecl = true;
- if (NewFD == 0) return 0;
- if (Redeclaration) {
+ if (!InvalidDecl) {
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
// An out-of-line member function declaration must also be a
@@ -2734,6 +2749,16 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
Diag(Definition->getLocation(), diag::note_previous_definition);
}
+ // Builtin functions cannot be defined.
+ if (unsigned BuiltinID = FD->getBuiltinID(Context)) {
+ if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
+ Diag(FD->getLocation(), diag::err_builtin_lib_definition) << FD;
+ Diag(FD->getLocation(), diag::note_builtin_lib_def_freestanding);
+ } else
+ Diag(FD->getLocation(), diag::err_builtin_definition) << FD;
+ FD->setInvalidDecl();
+ }
+
PushDeclContext(FnBodyScope, FD);
// Check the validity of our function parameters