aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Parse/DeclSpec.h4
-rw-r--r--lib/Parse/ParseDecl.cpp2
-rw-r--r--lib/Parse/ParseExpr.cpp2
-rw-r--r--lib/Parse/ParseExprCXX.cpp4
-rw-r--r--lib/Sema/Sema.h19
-rw-r--r--lib/Sema/SemaDecl.cpp272
-rw-r--r--lib/Sema/SemaDeclCXX.cpp12
-rw-r--r--lib/Sema/SemaExprCXX.cpp2
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp27
-rw-r--r--lib/Sema/SemaType.cpp15
-rw-r--r--test/Sema/invalid-decl.c7
-rw-r--r--test/Sema/tentative-decls.c8
-rw-r--r--test/SemaCXX/constructor-recovery.cpp7
-rw-r--r--test/SemaCXX/destructor.cpp1
14 files changed, 195 insertions, 187 deletions
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index 1be687be8e..e1f52a0246 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -1017,8 +1017,8 @@ public:
OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; }
- void setInvalidType(bool flag) { InvalidType = flag; }
- bool getInvalidType() const {
+ void setInvalidType(bool Val = true) { InvalidType = Val; }
+ bool isInvalidType() const {
return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 8268452430..f02b8a0682 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -37,7 +37,7 @@ Action::TypeResult Parser::ParseTypeName() {
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
- if (DeclaratorInfo.getInvalidType())
+ if (DeclaratorInfo.isInvalidType())
return true;
return Actions.ActOnTypeName(CurScope, DeclaratorInfo);
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index ec36fedc2d..55bc1862f5 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1338,7 +1338,7 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
ParamInfo.SetIdentifier(0, CaretLoc);
ParamInfo.SetRangeEnd(Tmp);
- if (ParamInfo.getInvalidType()) {
+ if (ParamInfo.isInvalidType()) {
// If there was an error parsing the arguments, they may have
// tried to use ^(x+y) which requires an argument list. Just
// skip the whole block literal.
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index f00edddffe..2f1b9c84d2 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -860,7 +860,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
}
ParenTypeId = false;
}
- if (DeclaratorInfo.getInvalidType()) {
+ if (DeclaratorInfo.isInvalidType()) {
SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
return ExprError();
}
@@ -938,7 +938,7 @@ bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
ParseSpecifierQualifierList(D.getMutableDeclSpec());
D.SetSourceRange(D.getDeclSpec().getSourceRange());
ParseDeclarator(D);
- return D.getInvalidType();
+ return D.isInvalidType();
}
// It's not a type, it has to be an expression list.
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 7426965a44..984576b5af 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -326,7 +326,8 @@ public:
// Type Analysis / Processing: SemaType.cpp.
//
QualType adjustParameterType(QualType T);
- QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc);
+ QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc,
+ bool &IsInvalid);
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
@@ -377,20 +378,18 @@ public:
Scope *S);
void DiagnoseFunctionSpecifiers(Declarator& D);
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R,
- Decl* PrevDecl, bool& InvalidDecl,
+ QualType R, Decl* PrevDecl,
bool &Redeclaration);
NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R,
- NamedDecl* PrevDecl, bool& InvalidDecl,
+ QualType R, NamedDecl* PrevDecl,
bool &Redeclaration);
- bool CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
+ void CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
bool &Redeclaration);
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, NamedDecl* PrevDecl,
bool IsFunctionDefinition,
- bool& InvalidDecl, bool &Redeclaration);
- bool CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+ bool &Redeclaration);
+ void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
bool &Redeclaration,
bool &OverloadableAttrRequired);
virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D);
@@ -518,10 +517,10 @@ public:
/// Subroutines of ActOnDeclarator().
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T);
- bool MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
+ void MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
- bool MergeVarDecl(VarDecl *New, Decl *Old);
+ void MergeVarDecl(VarDecl *New, Decl *Old);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
/// C++ Overloading.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9930dbc19b..64c85a2aad 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -471,11 +471,16 @@ NamespaceDecl *Sema::GetStdNamespace() {
/// 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.
+/// diagnostics as appropriate. If there was an error, set New to be invalid.
///
-bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
+void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
+ // If either decl is known invalid already, set the new one to be invalid and
+ // don't bother doing any merging checks.
+ if (New->isInvalidDecl() || OldD->isInvalidDecl())
+ return New->setInvalidDecl();
+
bool objc_types = false;
+
// Allow multiple definitions for ObjC built-in typedefs.
// FIXME: Verify the underlying types are equivalent!
if (getLangOptions().ObjC1) {
@@ -492,20 +497,17 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
if (!TypeID->isStr("Class"))
break;
Context.setObjCClassType(Context.getTypeDeclType(New));
- objc_types = true;
- return false;
+ return;
case 3:
if (!TypeID->isStr("SEL"))
break;
Context.setObjCSelType(Context.getTypeDeclType(New));
- objc_types = true;
- return false;
+ return;
case 8:
if (!TypeID->isStr("Protocol"))
break;
Context.setObjCProtoType(New->getUnderlyingType());
- objc_types = true;
- return false;
+ return;
}
// Fall through - the typedef name was not a builtin type.
}
@@ -514,9 +516,9 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
- if (!objc_types)
+ if (OldD->getLocation().isValid())
Diag(OldD->getLocation(), diag::note_previous_definition);
- return true;
+ return New->setInvalidDecl();
}
// Determine the "old" type we'll use for checking and diagnostics.
@@ -534,12 +536,13 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
Context.getCanonicalType(New->getUnderlyingType())) {
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
<< New->getUnderlyingType() << OldType;
- if (!objc_types)
+ if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_definition);
- return true;
+ return New->setInvalidDecl();
}
- if (objc_types) return false;
- if (getLangOptions().Microsoft) return false;
+
+ if (objc_types || getLangOptions().Microsoft)
+ return;
// C++ [dcl.typedef]p2:
// In a given non-class scope, a typedef specifier can be used to
@@ -547,11 +550,11 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
// to the type to which it already refers.
if (getLangOptions().CPlusPlus) {
if (!isa<CXXRecordDecl>(CurContext))
- return false;
+ return;
Diag(New->getLocation(), diag::err_redefinition)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return true;
+ return New->setInvalidDecl();
}
// If we have a redefinition of a typedef in C, emit a warning. This warning
@@ -560,7 +563,7 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
Diag(New->getLocation(), diag::warn_redefinition_of_typedef)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return false;
+ return;
}
/// DeclhasAttr - returns true if decl Declaration already has the target
@@ -883,14 +886,19 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
/// definitions here, since the initializer hasn't been attached.
///
-bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
+void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
+ // If either decl is invalid, make sure the new one is marked invalid and
+ // don't do any other checking.
+ if (New->isInvalidDecl() || OldD->isInvalidDecl())
+ return New->setInvalidDecl();
+
// 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 true;
+ return New->setInvalidDecl();
}
MergeAttributes(New, Old, Context);
@@ -901,7 +909,7 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
Diag(New->getLocation(), diag::err_redefinition_different_type)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return true;
+ return New->setInvalidDecl();
}
New->setType(MergedT);
@@ -910,7 +918,7 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
(Old->getStorageClass() == VarDecl::None || Old->hasExternalStorage())) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return true;
+ return New->setInvalidDecl();
}
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
@@ -927,7 +935,7 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
Old->getStorageClass() == VarDecl::Static) {
Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return true;
+ return New->setInvalidDecl();
}
// Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
@@ -940,7 +948,7 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
!New->getLexicalDeclContext()->isRecord())) {
Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return true;
+ return New->setInvalidDecl();
}
if (New->isThreadSpecified() && !Old->isThreadSpecified()) {
@@ -953,8 +961,6 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
// Keep a chain of previous declarations.
New->setPreviousDeclaration(Old);
-
- return false;
}
/// CheckParmsForFunctionDef - Check that the parameters of the given
@@ -1337,7 +1343,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
// All of these full declarators require an identifier. If it doesn't have
// one, the ParsedFreeStandingDeclSpec action should be used.
if (!Name) {
- if (!D.getInvalidType()) // Reject this if we think it is valid.
+ if (!D.isInvalidType()) // Reject this if we think it is valid.
Diag(D.getDeclSpec().getSourceRange().getBegin(),
diag::err_declarator_need_ident)
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
@@ -1353,11 +1359,10 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
DeclContext *DC;
NamedDecl *PrevDecl;
NamedDecl *New;
- bool InvalidDecl = false;
QualType R = GetTypeForDeclarator(D, S);
if (R.isNull()) {
- InvalidDecl = true;
+ D.setInvalidType();
R = Context.IntTy;
if (IsFunctionDefinition) // int(...)
R = Context.getFunctionType(R, 0, 0, true, 0);
@@ -1368,7 +1373,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
if (D.getCXXScopeSpec().isInvalid()) {
DC = CurContext;
PrevDecl = 0;
- InvalidDecl = true;
+ D.setInvalidType();
} else if (!D.getCXXScopeSpec().isSet()) {
LookupNameKind NameKind = LookupOrdinaryName;
@@ -1430,14 +1435,16 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
else
Diag(L, diag::err_invalid_declarator_scope)
<< Name << cast<NamedDecl>(DC) << R;
- InvalidDecl = true;
+ D.setInvalidType();
}
}
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
- InvalidDecl = InvalidDecl
- || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+ if (!D.isInvalidType())
+ if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl))
+ D.setInvalidType();
+
// Just pretend that we didn't see the previous declaration.
PrevDecl = 0;
}
@@ -1452,15 +1459,12 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
bool Redeclaration = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
- New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl,
- InvalidDecl, Redeclaration);
+ New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
} else if (R->isFunctionType()) {
New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl,
- IsFunctionDefinition, InvalidDecl,
- Redeclaration);
+ IsFunctionDefinition, Redeclaration);
} else {
- New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl,
- InvalidDecl, Redeclaration);
+ New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
}
if (New == 0)
@@ -1468,11 +1472,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
// If this has an identifier and is not an invalid redeclaration,
// add it to the scope stack.
- if (Name && !(Redeclaration && InvalidDecl))
+ if (Name && !(Redeclaration && New->isInvalidDecl()))
PushOnScopeChains(New, S);
- // If any semantic error occurred, mark the decl as invalid.
- if (D.getInvalidType() || InvalidDecl)
- New->setInvalidDecl();
return DeclPtrTy::make(New);
}
@@ -1568,13 +1569,12 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
NamedDecl*
Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, Decl* PrevDecl, bool& InvalidDecl,
- bool &Redeclaration) {
+ QualType R, Decl* PrevDecl, bool &Redeclaration) {
// Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
<< D.getCXXScopeSpec().getRange();
- InvalidDecl = true;
+ D.setInvalidType();
// Pretend we didn't see the scope specifier.
DC = 0;
}
@@ -1591,6 +1591,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TypedefDecl *NewTD = ParseTypedefDecl(S, D, R);
if (!NewTD) return 0;
+
+ if (D.isInvalidType())
+ NewTD->setInvalidDecl();
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(NewTD, D);
@@ -1598,8 +1601,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// in an outer scope, it isn't the same thing.
if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
Redeclaration = true;
- if (MergeTypeDefDecl(NewTD, PrevDecl))
- InvalidDecl = true;
+ MergeTypeDefDecl(NewTD, PrevDecl);
}
// C99 6.7.7p2: If a typedef name specifies a variably modified type
@@ -1622,7 +1624,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
else
Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);
- InvalidDecl = true;
+ NewTD->setInvalidDecl();
}
}
}
@@ -1696,7 +1698,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
NamedDecl*
Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R,NamedDecl* PrevDecl, bool& InvalidDecl,
+ QualType R,NamedDecl* PrevDecl,
bool &Redeclaration) {
DeclarationName Name = GetNameForDeclarator(D);
@@ -1718,7 +1720,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// mutable can only appear on non-static class members, so it's always
// an error here
Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
- InvalidDecl = true;
+ D.setInvalidType();
SC = VarDecl::None;
break;
}
@@ -1737,7 +1739,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// appear in the declaration specifiers in an external declaration.
if (SC == VarDecl::Auto || SC == VarDecl::Register) {
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
- InvalidDecl = true;
+ D.setInvalidType();
}
}
if (DC->isRecord() && !CurContext->isRecord()) {
@@ -1757,6 +1759,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// FIXME: Move to DeclGroup...
D.getDeclSpec().getSourceRange().getBegin());
+ if (D.isInvalidType())
+ NewVD->setInvalidDecl();
+
if (D.getDeclSpec().isThreadSpecified()) {
if (NewVD->hasLocalStorage())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
@@ -1797,22 +1802,21 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
<< D.getCXXScopeSpec().getRange();
PrevDecl = 0;
- InvalidDecl = true;
+ NewVD->setInvalidDecl();
}
} else if (D.getCXXScopeSpec().isSet()) {
// No previous declaration in the qualifying scope.
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
<< Name << D.getCXXScopeSpec().getRange();
- InvalidDecl = true;
+ NewVD->setInvalidDecl();
}
- if (CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration))
- InvalidDecl = true;
+ CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration);
// If this is a locally-scoped extern C variable, update the map of
// such variables.
if (CurContext->isFunctionOrMethod() && NewVD->isExternC(Context) &&
- !InvalidDecl)
+ !NewVD->isInvalidDecl())
RegisterLocallyScopedExternCDecl(NewVD, PrevDecl, S);
return NewVD;
@@ -1826,23 +1830,25 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/// check variables after they have been parsed and their declarators
/// have been translated into a declaration, and to check
///
-/// \returns true if an error was encountered, false otherwise.
-bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
+/// Sets NewVD->isInvalidDecl() if an error was encountered.
+void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
bool &Redeclaration) {
- bool Invalid = false;
-
+ // If the decl is already known invalid, don't check it.
+ if (NewVD->isInvalidDecl())
+ return;
+
QualType T = NewVD->getType();
if (T->isObjCInterfaceType()) {
Diag(NewVD->getLocation(), diag::err_statically_allocated_object);
- Invalid = true;
+ return NewVD->setInvalidDecl();
}
// The variable can not have an abstract class type.
if (RequireNonAbstractType(NewVD->getLocation(), T,
diag::err_abstract_type_in_decl,
AbstractVariableType))
- Invalid = true;
+ return NewVD->setInvalidDecl();
// Emit an error if an address space was applied to decl with local storage.
// This includes arrays of objects with address space qualifiers, but not
@@ -1850,7 +1856,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
// ISO/IEC TR 18037 S5.1.2
if (NewVD->hasLocalStorage() && (T.getAddressSpace() != 0)) {
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
- Invalid = true;
+ return NewVD->setInvalidDecl();
}
if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
@@ -1866,34 +1872,35 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
bool SizeIsNegative;
QualType FixedTy =
TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
- if (!FixedTy.isNull()) {
- Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
- NewVD->setType(FixedTy);
- } else if (T->isVariableArrayType()) {
- Invalid = true;
-
+
+ if (FixedTy.isNull() && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
// FIXME: This won't give the correct result for
// int a[10][n];
SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
-
+
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
- << SizeRange;
+ << SizeRange;
else if (NewVD->getStorageClass() == VarDecl::Static)
Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
- << SizeRange;
+ << SizeRange;
else
Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage)
- << SizeRange;
- } else {
- Invalid = true;
-
+ << SizeRange;
+ return NewVD->setInvalidDecl();
+ }
+
+ if (FixedTy.isNull()) {
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
else
Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage);
+ return NewVD->setInvalidDecl();
}
+
+ Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
+ NewVD->setType(FixedTy);
}
if (!PrevDecl && NewVD->isExternC(Context)) {
@@ -1906,26 +1913,22 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
PrevDecl = Pos->second;
}
- if (!Invalid && T->isVoidType() && !NewVD->hasExternalStorage()) {
+ if (T->isVoidType() && !NewVD->hasExternalStorage()) {
Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
<< T;
- Invalid = true;
+ return NewVD->setInvalidDecl();
}
if (PrevDecl) {
Redeclaration = true;
- if (MergeVarDecl(NewVD, PrevDecl))
- Invalid = true;
+ MergeVarDecl(NewVD, PrevDecl);
}
-
- return NewVD->isInvalidDecl() || Invalid;
}
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, NamedDecl* PrevDecl,
- bool IsFunctionDefinition,
- bool &InvalidDecl, bool &Redeclaration) {
+ bool IsFunctionDefinition, bool &Redeclaration) {
assert(R.getTypePtr()->isFunctionType());
DeclarationName Name = GetNameForDeclarator(D);
@@ -1937,7 +1940,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
case DeclSpec::SCS_mutable:
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_typecheck_sclass_func);
- InvalidDecl = true;
+ D.setInvalidType();
break;
case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
case DeclSpec::SCS_extern: SC = FunctionDecl::Extern; break;
@@ -1973,14 +1976,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
R->getAsFunctionType()->getResultType(),
diag::err_abstract_type_in_decl,
AbstractReturnType))
- InvalidDecl = true;
+ D.setInvalidType();
// Do not allow returning a objc interface by-value.
if (R->getAsFunctionType()->getResultType()->isObjCInterfaceType()) {
Diag(D.getIdentifierLoc(),
diag::err_object_cannot_be_passed_returned_by_value) << 0
<< R->getAsFunctionType()->getResultType();
- InvalidDecl = true;
+ D.setInvalidType();
}
bool isVirtualOkay = false;
@@ -1990,7 +1993,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
assert(DC->isRecord() &&
"Constructors can only be declared in a member context");
- InvalidDecl = InvalidDecl || CheckConstructorDeclarator(D, R, SC);
+ if (!D.isInvalidType())
+ D.setInvalidType(CheckConstructorDeclarator(D, R, SC));
// Create the new declaration
NewFD = CXXConstructorDecl::Create(Context,
@@ -2001,8 +2005,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
} else if (D.getKind() == Declarator::DK_Destructor) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {
- InvalidDecl = InvalidDecl || CheckDestructorDeclarator(D, R, SC);
-
+ if (!D.isInvalidType())
+ D.setInvalidType(CheckDestructorDeclarator(D, R, SC));
+
NewFD = CXXDestructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
D.getIdentifierLoc(), Name, R,
@@ -2020,7 +2025,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/*hasPrototype=*/true,
// FIXME: Move to DeclGroup...
D.getDeclSpec().getSourceRange().getBegin());
- InvalidDecl = true;
+ D.setInvalidType();
}
} else if (D.getKind() == Declarator::DK_Conversion) {
if (!DC->isRecord()) {
@@ -2028,7 +2033,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
diag::err_conv_function_not_member);
return 0;
} else {
- InvalidDecl = InvalidDecl || CheckConversionDeclarator(D, R, SC);
+ if (!D.isInvalidType())
+ D.setInvalidType(CheckConversionDeclarator(D, R, SC));
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
D.getIdentifierLoc(), Name, R,
@@ -2062,7 +2068,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
D.getDeclSpec().getSourceRange().getBegin());
}
- if (InvalidDecl)
+ if (D.isInvalidType())
NewFD->setInvalidDecl();
// Set the lexical context. If the declarator has a C++
@@ -2079,7 +2085,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// function is also virtual if it overrides an already virtual
// function. This is important to do here because it's part of the
// declaration.
- if (isVirtual && !InvalidDecl) {
+ if (isVirtual && !NewFD->isInvalidDecl()) {
if (!isVirtualOkay) {
Diag(D.getDeclSpec().getVirtualSpecLoc(),
diag::err_virtual_non_function);
@@ -2218,17 +2224,16 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Perform semantic checking on the function declaration.
bool OverloadableAttrRequired = false; // FIXME: HACK!
- if (CheckFunctionDeclaration(NewFD, PrevDecl, Redeclaration,
- /*FIXME:*/OverloadableAttrRequired))
- InvalidDecl = true;
+ CheckFunctionDeclaration(NewFD, PrevDecl, Redeclaration,
+ /*FIXME:*/OverloadableAttrRequired);
- if (D.getCXXScopeSpec().isSet() && !InvalidDecl) {
+ if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
// An out-of-line member function declaration must also be a
// definition (C++ [dcl.meaning]p1).
if (!IsFunctionDefinition) {
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
- InvalidDecl = true;
+ NewFD->setInvalidDecl();
} else if (!Redeclaration) {
// The user tried to provide an out-of-line definition for a
// function that is a member of a class or namespace, but there
@@ -2246,7 +2251,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// whether the parameter types are references).
Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
<< cast<NamedDecl>(DC) << D.getCXXScopeSpec().getRange();
- InvalidDecl = true;
+ NewFD->setInvalidDecl();
LookupResult Prev = LookupQualifiedName(DC, Name, LookupOrdinaryName,
true);
@@ -2284,7 +2289,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// If this is a locally-scoped extern C function, update the
// map of such names.
if (CurContext->isFunctionOrMethod() && NewFD->isExternC(Context)
- && !InvalidDecl)
+ && !NewFD->isInvalidDecl())
RegisterLocallyScopedExternCDecl(NewFD, PrevDecl, S);
return NewFD;
@@ -2300,18 +2305,21 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/// that have been instantiated via C++ template instantiation (called
/// via InstantiateDecl).
///
-/// \returns true if there was an error, false otherwise.
-bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
bool &Redeclaration,
bool &OverloadableAttrRequired) {
- bool InvalidDecl = false;
+ // If NewFD is already known erroneous, don't do any of this checking.
+ if (NewFD->isInvalidDecl())
+ return;
// Semantic checking for this function declaration (in isolation).
if (getLangOptions().CPlusPlus) {
// C++-specific checks.
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
- InvalidDecl = InvalidDecl || CheckConstructor(Constructor);
- else if (isa<CXXDestructorDecl>(NewFD)) {
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+ if (CheckConstructor(Constructor))
+ return NewFD->setInvalidDecl();
+ } else if (isa<CXXDestructorDecl>(NewFD)) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
Record->setUserDeclaredDestructor(true);
// C++ [class]p4: A POD-struct is an aggregate class that has [...] no
@@ -2328,7 +2336,7 @@ bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
// Extra checking for C++ overloaded operators (C++ [over.oper]).
if (NewFD->isOverloadedOperator() &&
CheckOverloadedOperatorDeclaration(NewFD))
- InvalidDecl = true;
+ return NewFD->setInvalidDecl();
}
// C99 6.7.4p6:
@@ -2386,7 +2394,6 @@ bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
if (!NewFD->getType()->getAsFunctionProtoType()) {
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_no_prototype)
<< NewFD;
- InvalidDecl = true;
Redeclaration = true;
// Turn this into a variadic function with no parameters.
@@ -2394,6 +2401,7 @@ bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
NewFD->getType()->getAsFunctionType()->getResultType(),
0, 0, true, 0);
NewFD->setType(R);
+ return NewFD->setInvalidDecl();
}
}
@@ -2411,21 +2419,17 @@ bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
// NewFD and OldDecl represent declarations that need to be
// merged.
if (MergeFunctionDecl(NewFD, OldDecl))
- InvalidDecl = true;
+ return NewFD->setInvalidDecl();
- if (!InvalidDecl)
- NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+ NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
}
}
- if (getLangOptions().CPlusPlus && !CurContext->isRecord()) {
- // In C++, check default arguments now that we have merged decls. Unless
- // the lexical context is the class, because in this case this is done
- // during delayed parsing anyway.
+ // In C++, check default arguments now that we have merged decls. Unless
+ // the lexical context is the class, because in this case this is done
+ // during delayed parsing anyway.
+ if (getLangOptions().CPlusPlus && !CurContext->isRecord())
CheckCXXDefaultArguments(NewFD);
- }
-
- return InvalidDecl || NewFD->isInvalidDecl();
}
bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
@@ -2798,9 +2802,6 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (getLangOptions().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
- // In this context, we *do not* check D.getInvalidType(). If the declarator
- // type was invalid, GetTypeForDeclarator() still returns a "valid" type,
- // though it will not reflect the user specified type.
QualType parmDeclType = GetTypeForDeclarator(D, S);
if (parmDeclType.isNull()) {
D.setInvalidType(true);
@@ -2850,7 +2851,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
D.getIdentifierLoc(), II, T,
parmDeclType, StorageClass, 0);
- if (D.getInvalidType())
+ if (D.isInvalidType())
New->setInvalidDecl();
// Parameter declarators cannot be interface types. All ObjC objects are
@@ -3210,7 +3211,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) {
TD->setTypedefForAnonDecl(NewTD);
}
- if (D.getInvalidType())
+ if (D.isInvalidType())
NewTD->setInvalidDecl();
return NewTD;
}
@@ -3712,6 +3713,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
Declarator *D) {
IdentifierInfo *II = Name.getAsIdentifierInfo();
bool InvalidDecl = false;
+ if (D) InvalidDecl = D->isInvalidType();
// If we receive a broken type, recover by assuming 'int' and
// marking this declaration as invalid.
@@ -3753,6 +3755,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, BitWidth,
Mutable);
+ if (InvalidDecl)
+ NewFD->setInvalidDecl();
if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
Diag(Loc, diag::err_duplicate_member) << II;
@@ -3772,9 +3776,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (T.isObjCGCWeak())
Diag(Loc, diag::warn_attribute_weak_on_field);
- if (InvalidDecl)
- NewFD->setInvalidDecl();
-
NewFD->setAccess(AS);
// C++ [dcl.init.aggr]p1:
@@ -3820,16 +3821,15 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
// example, unnamed unions inject all members into the struct namespace!
QualType T = GetTypeForDeclarator(D, S);
- bool InvalidDecl = D.getInvalidType();
- if (T.isNull()) {
- InvalidDecl = true;
- T = Context.IntTy;
- }
+ if (T.isNull()) {
+ D.setInvalidType();
+ T = Context.IntTy;
+ }
if (BitWidth) {
// 6.7.2.1p3, 6.7.2.1p4
if (VerifyBitField(Loc, II, T, BitWidth)) {
- InvalidDecl = true;
+ D.setInvalidType();
DeleteExpr(BitWidth);
BitWidth = 0;
}
@@ -3844,7 +3844,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
// than a variably modified type.
if (T->isVariablyModifiedType()) {
Diag(Loc, diag::err_typecheck_ivar_variable_size);
- InvalidDecl = true;
+ D.setInvalidType();
}
// Get the visibility (access control) for this ivar.
@@ -3869,7 +3869,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
// Process attributes attached to the ivar.
ProcessDeclAttributes(NewID, D);
- if (D.getInvalidType() || InvalidDecl)
+ if (D.isInvalidType())
NewID->setInvalidDecl();
if (II) {
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 82830ef4ad..e3a0063b0d 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2547,7 +2547,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
QualType ExDeclType = GetTypeForDeclarator(D, S);
SourceLocation Begin = D.getDeclSpec().getSourceRange().getBegin();
- bool Invalid = false;
+ bool Invalid = D.isInvalidType();
// Arrays and functions decay.
if (ExDeclType->isArrayType())
@@ -2597,15 +2597,15 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
II, ExDeclType, VarDecl::None, Begin);
- if (D.getInvalidType() || Invalid)
- ExDecl->setInvalidDecl();
-
- if (D.getCXXScopeSpec().isSet()) {
+ if (D.getCXXScopeSpec().isSet() && !Invalid) {
Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
<< D.getCXXScopeSpec().getRange();
- ExDecl->setInvalidDecl();
+ Invalid = true;
}
+ if (Invalid)
+ ExDecl->setInvalidDecl();
+
// Add the exception declaration into this scope.
S->AddDecl(DeclPtrTy::make(ExDecl));
if (II)
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 753fd5efc1..6b0c04440a 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -243,7 +243,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, Skip);
- if (D.getInvalidType())
+ if (D.isInvalidType())
return ExprError();
if (CheckAllocatedType(AllocType, D))
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 4639511023..d7e81127a7 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -124,9 +124,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// FIXME: In theory, we could have a previous declaration for
// variables that are not static data members.
bool Redeclaration = false;
- if (SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration))
- Var->setInvalidDecl();
-
+ SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration);
Owner->addDecl(SemaRef.Context, Var);
if (D->getInit()) {
@@ -322,9 +320,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
PrevDecl = 0;
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
- if (SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
- /*FIXME:*/OverloadableAttrRequired))
- Method->setInvalidDecl();
+ SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
+ /*FIXME:*/OverloadableAttrRequired);
if (!Method->isInvalidDecl() || !PrevDecl)
Owner->addDecl(SemaRef.Context, Method);
@@ -366,12 +363,10 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
PrevDecl = 0;
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
- if (SemaRef.CheckFunctionDeclaration(Constructor, PrevDecl, Redeclaration,
- /*FIXME:*/OverloadableAttrRequired))
- Constructor->setInvalidDecl();
+ SemaRef.CheckFunctionDeclaration(Constructor, PrevDecl, Redeclaration,
+ /*FIXME:*/OverloadableAttrRequired);
- if (!Constructor->isInvalidDecl())
- Owner->addDecl(SemaRef.Context, Constructor);
+ Owner->addDecl(SemaRef.Context, Constructor);
return Constructor;
}
@@ -396,9 +391,8 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
NamedDecl *PrevDecl = 0;
- if (SemaRef.CheckFunctionDeclaration(Destructor, PrevDecl, Redeclaration,
- /*FIXME:*/OverloadableAttrRequired))
- Destructor->setInvalidDecl();
+ SemaRef.CheckFunctionDeclaration(Destructor, PrevDecl, Redeclaration,
+ /*FIXME:*/OverloadableAttrRequired);
Owner->addDecl(SemaRef.Context, Destructor);
return Destructor;
}
@@ -426,9 +420,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
NamedDecl *PrevDecl = 0;
- if (SemaRef.CheckFunctionDeclaration(Conversion, PrevDecl, Redeclaration,
- /*FIXME:*/OverloadableAttrRequired))
- Conversion->setInvalidDecl();
+ SemaRef.CheckFunctionDeclaration(Conversion, PrevDecl, Redeclaration,
+ /*FIXME:*/OverloadableAttrRequired);
Owner->addDecl(SemaRef.Context, Conversion);
return Conversion;
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 62d2489b34..7519aff630 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -50,7 +50,8 @@ QualType Sema::adjustParameterType(QualType T) {
/// \returns The type described by the declaration specifiers, or NULL
/// if there was an error.
QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
- SourceLocation DeclLoc) {
+ SourceLocation DeclLoc,
+ bool &isInvalid) {
// FIXME: Should move the logic from DeclSpec::Finish to here for validity
// checking.
QualType Result;
@@ -205,8 +206,15 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
DeclLoc = DS.getSourceRange().getBegin();
Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
<< DS.getSourceRange();
+ isInvalid = true;
}
}
+
+ // If this is a reference to an invalid typedef, propagate the invalidity.
+ if (TypedefType *TDT = dyn_cast<TypedefType>(Result))
+ if (TDT->getDecl()->isInvalidDecl())
+ isInvalid = true;
+
// TypeQuals handled by caller.
break;
}
@@ -614,9 +622,12 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
// the first return statement.
T = Context.DependentTy;
} else {
- T = ConvertDeclSpecToType(DS, D.getIdentifierLoc());
+ bool isInvalid = false;
+ T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid);
if (T.isNull())
return T;
+ if (isInvalid)
+ D.setInvalidType(true);
}
break;
}
diff --git a/test/Sema/invalid-decl.c b/test/Sema/invalid-decl.c
index e9130c80a9..8c458008cb 100644
--- a/test/Sema/invalid-decl.c
+++ b/test/Sema/invalid-decl.c
@@ -6,11 +6,14 @@ void test() {
// PR2400
-typedef xtype (*zend_stream_fsizer_t)(void* handle); // expected-error {{function cannot return array or function type}} expected-warning {{type specifier missing, defaults to 'int'}} expected-warning {{type specifier missing, defaults to 'int'}}
+typedef xtype (*x)(void* handle); // expected-error {{function cannot return array or function type}} expected-warning {{type specifier missing, defaults to 'int'}} expected-warning {{type specifier missing, defaults to 'int'}}
+
+typedef void ytype();
+
typedef struct _zend_module_entry zend_module_entry;
struct _zend_module_entry {
- xtype globals_size; // expected-error {{field 'globals_size' declared as a function}}
+ ytype globals_size; // expected-error {{field 'globals_size' declared as a function}}
};
zend_module_entry openssl_module_entry = {
diff --git a/test/Sema/tentative-decls.c b/test/Sema/tentative-decls.c
index 85b5ed76bd..e3c893c777 100644
--- a/test/Sema/tentative-decls.c
+++ b/test/Sema/tentative-decls.c
@@ -23,8 +23,8 @@ int i1 = 1; // expected-note {{previous definition is here}}
int i1 = 2; // expected-error {{redefinition of 'i1'}}
int i1;
int i1;
-extern int i1; // expected-note {{previous definition is here}}
-static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}}
+extern int i5; // expected-note {{previous definition is here}}
+static int i5; // expected-error{{static declaration of 'i5' follows non-static declaration}}
static int i2 = 5; // expected-note 1 {{previous definition is here}}
int i2 = 3; // expected-error{{non-static declaration of 'i2' follows static declaration}}
@@ -47,8 +47,8 @@ int redef[]; // expected-note {{previous definition is here}}
int redef[11]; // expected-error{{redefinition of 'redef'}}
void func() {
- extern int i1; // expected-note {{previous definition is here}}
- static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}}
+ extern int i6; // expected-note {{previous definition is here}}
+ static int i6; // expected-error{{static declaration of 'i6' follows non-static declaration}}
}
void func2(void)
diff --git a/test/SemaCXX/constructor-recovery.cpp b/test/SemaCXX/constructor-recovery.cpp
index f2f9f43a10..50fdc9622e 100644
--- a/test/SemaCXX/constructor-recovery.cpp
+++ b/test/SemaCXX/constructor-recovery.cpp
@@ -1,9 +1,10 @@
// RUN: clang-cc -fsyntax-only -verify %s
-struct C {
- virtual C() = 0; // expected-error{{constructor cannot be declared 'virtual'}}
+struct C { // expected-note {{candidate function}}
+ virtual C() = 0; // expected-error{{constructor cannot be declared 'virtual'}} \
+ expected-note {{candidate function}}
};
void f() {
- C c;
+ C c; // expected-error {{call to constructor of 'c' is ambiguous}}
}
diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp
index 3ba5fd5946..c60045bb59 100644
--- a/test/SemaCXX/destructor.cpp
+++ b/test/SemaCXX/destructor.cpp
@@ -23,6 +23,7 @@ struct D {
// expected-error{{destructor cannot be variadic}}
};
+
struct E;
typedef E E_typedef;