diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-04-30 13:56:41 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-04-30 13:56:41 +0000 |
commit | dc7a4f5d7a7e3b60d4dc4a80338d7a2728540998 (patch) | |
tree | 0fdbc7f2427ae39e5c561332fb0d7c04e4dcb65b /lib/Sema/SemaDecl.cpp | |
parent | 24cb36d9c212f82b3d9aedd34be27ae4911bfdba (diff) |
Don't treat a non-deduced 'auto' type as being type-dependent. Instead, there
are now two distinct canonical 'AutoType's: one is the undeduced 'auto'
placeholder type, and the other is a deduced-but-dependent type. All
deduced-to-a-non-dependent-type cases are still non-canonical.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180789 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 122 |
1 files changed, 68 insertions, 54 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9a3499dc39..1e5e5bb259 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2798,8 +2798,7 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { QualType MergedT; if (getLangOpts().CPlusPlus) { - AutoType *AT = New->getType()->getContainedAutoType(); - if (AT && !AT->isDeduced()) { + if (New->getType()->isUndeducedType()) { // We don't know what the new type is until the initializer is attached. return; } else if (Context.hasSameType(New->getType(), Old->getType())) { @@ -5142,27 +5141,18 @@ static bool mayConflictWithNonVisibleExternC(const T *ND) { return ND->isExternC(); } -/// \brief Perform semantic checking on a newly-created variable -/// declaration. -/// -/// This routine performs all of the type-checking required for a -/// variable declaration once it has been built. It is used both to -/// check variables after they have been parsed and their declarators -/// have been translated into a declaration, and to check variables -/// that have been instantiated from a template. -/// -/// Sets NewVD->isInvalidDecl() if an error was encountered. -/// -/// Returns true if the variable declaration is a redeclaration. -bool Sema::CheckVariableDeclaration(VarDecl *NewVD, - LookupResult &Previous) { +void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { // If the decl is already known invalid, don't check it. if (NewVD->isInvalidDecl()) - return false; + return; TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo(); QualType T = TInfo->getType(); + // Defer checking an 'auto' type until its initializer is attached. + if (T->isUndeducedType()) + return; + if (T->isObjCObjectType()) { Diag(NewVD->getLocation(), diag::err_statically_allocated_object) << FixItHint::CreateInsertion(NewVD->getLocation(), "*"); @@ -5177,7 +5167,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl); NewVD->setInvalidDecl(); - return false; + return; } // OpenCL v1.2 s6.5 - All program scope variables must be declared in the @@ -5187,7 +5177,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, && !T->isSamplerT()){ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space); NewVD->setInvalidDecl(); - return false; + return; } // OpenCL v1.2 s6.8 -- The static qualifier is valid only in program @@ -5196,7 +5186,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, && NewVD->isStaticLocal()) { Diag(NewVD->getLocation(), diag::err_static_function_scope); NewVD->setInvalidDecl(); - return false; + return; } if (NewVD->hasLocalStorage() && T.isObjCGCWeak() @@ -5237,7 +5227,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage) << SizeRange; NewVD->setInvalidDecl(); - return false; + return; } if (FixedTInfo == 0) { @@ -5246,7 +5236,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, else Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage); NewVD->setInvalidDecl(); - return false; + return; } Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); @@ -5254,6 +5244,54 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NewVD->setTypeSourceInfo(FixedTInfo); } + if (T->isVoidType() && NewVD->isThisDeclarationADefinition()) { + Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) + << T; + NewVD->setInvalidDecl(); + return; + } + + if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) { + Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); + NewVD->setInvalidDecl(); + return; + } + + if (isVM && NewVD->hasAttr<BlocksAttr>()) { + Diag(NewVD->getLocation(), diag::err_block_on_vm); + NewVD->setInvalidDecl(); + return; + } + + if (NewVD->isConstexpr() && !T->isDependentType() && + RequireLiteralType(NewVD->getLocation(), T, + diag::err_constexpr_var_non_literal)) { + // Can't perform this check until the type is deduced. + NewVD->setInvalidDecl(); + return; + } +} + +/// \brief Perform semantic checking on a newly-created variable +/// declaration. +/// +/// This routine performs all of the type-checking required for a +/// variable declaration once it has been built. It is used both to +/// check variables after they have been parsed and their declarators +/// have been translated into a declaration, and to check variables +/// that have been instantiated from a template. +/// +/// Sets NewVD->isInvalidDecl() if an error was encountered. +/// +/// Returns true if the variable declaration is a redeclaration. +bool Sema::CheckVariableDeclaration(VarDecl *NewVD, + LookupResult &Previous) { + CheckVariableDeclarationType(NewVD); + + // If the decl is already known invalid, don't check it. + if (NewVD->isInvalidDecl()) + return false; + // If we did not find anything by this name, look for a non-visible // extern "C" declaration with the same name. // @@ -5292,32 +5330,6 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, // Filter out any non-conflicting previous declarations. filterNonConflictingPreviousDecls(Context, NewVD, Previous); - if (T->isVoidType() && NewVD->isThisDeclarationADefinition()) { - Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) - << T; - NewVD->setInvalidDecl(); - return false; - } - - if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) { - Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); - NewVD->setInvalidDecl(); - return false; - } - - if (isVM && NewVD->hasAttr<BlocksAttr>()) { - Diag(NewVD->getLocation(), diag::err_block_on_vm); - NewVD->setInvalidDecl(); - return false; - } - - if (NewVD->isConstexpr() && !T->isDependentType() && - RequireLiteralType(NewVD->getLocation(), T, - diag::err_constexpr_var_non_literal)) { - NewVD->setInvalidDecl(); - return false; - } - if (!Previous.empty()) { MergeVarDecl(NewVD, Previous, PreviousWasHidden); return true; @@ -7284,10 +7296,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. - AutoType *Auto = 0; - if (TypeMayContainAuto && - (Auto = VDecl->getType()->getContainedAutoType()) && - !Auto->isDeduced()) { + if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) { Expr *DeduceInit = Init; // Initializer could be a C++ direct-initializer. Deduction only works if it // contains exactly one expression. @@ -7357,6 +7366,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // the previously declared type. if (VarDecl *Old = VDecl->getPreviousDecl()) MergeVarDeclTypes(VDecl, Old, /*OldWasHidden*/ false); + + // Check the deduced type is valid for a variable declaration. + CheckVariableDeclarationType(VDecl); + if (VDecl->isInvalidDecl()) + return; } if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) { @@ -8190,8 +8204,8 @@ Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, // Don't reissue diagnostics when instantiating a template. if (AT && D->isInvalidDecl()) break; - if (AT && AT->isDeduced()) { - QualType U = AT->getDeducedType(); + QualType U = AT ? AT->getDeducedType() : QualType(); + if (!U.isNull()) { CanQualType UCanon = Context.getCanonicalType(U); if (Deduced.isNull()) { Deduced = U; |