aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-04-30 13:56:41 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-04-30 13:56:41 +0000
commitdc7a4f5d7a7e3b60d4dc4a80338d7a2728540998 (patch)
tree0fdbc7f2427ae39e5c561332fb0d7c04e4dcb65b /lib/Sema/SemaDecl.cpp
parent24cb36d9c212f82b3d9aedd34be27ae4911bfdba (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.cpp122
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;