This is a pretty big cleanup for how invalid decl/type are handle.

This gets rid of a bunch of random InvalidDecl bools in sema, changing
us to use the following approach:

1. When analyzing a declspec or declarator, if an error is found, we 
   set a bit in Declarator saying that it is invalid.
2. Once the Decl is created by sema, we immediately set the isInvalid
   bit on it from what is in the declarator.  From this point on, sema
   consistently looks at and sets the bit on the decl.

This gives a very clear separation of concerns and simplifies a bunch
of code.  In addition to this, this patch makes these changes:

1. it renames DeclSpec::getInvalidType() -> isInvalidType().
2. various "merge" functions no longer return bools: they just set the
   invalid bit on the dest decl if invalid.
3. The ActOnTypedefDeclarator/ActOnFunctionDeclarator/ActOnVariableDeclarator
   methods now set invalid on the decl returned instead of returning an
   invalid bit byref.
4. In SemaType, refering to a typedef that was invalid now propagates the
   bit into the resultant type.  Stuff declared with the invalid typedef
   will now be marked invalid.
5. Various methods like CheckVariableDeclaration now return void and set the
   invalid bit on the decl they check.


There are a few minor changes to tests with this, but the only major bad
result is test/SemaCXX/constructor-recovery.cpp.  I'll take a look at this
next.

llvm-svn: 70020
This commit is contained in:
Chris Lattner 2009-04-25 08:06:05 +00:00
parent 0c155e6dbe
commit f6d1c9c7f0
14 changed files with 195 additions and 187 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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) {

View File

@ -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)

View File

@ -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))

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 = {

View File

@ -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)

View File

@ -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}}
}

View File

@ -23,6 +23,7 @@ struct D {
// expected-error{{destructor cannot be variadic}}
};
struct E;
typedef E E_typedef;