summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-08-11 22:25:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-08-11 22:25:46 +0000
commit7873de0cf65f48e6c8169691ee7eb203b89bfac5 (patch)
tree361febace1eab46aacfef2f710bf7720448f7f3a /clang/lib/Sema/SemaDecl.cpp
parentfa7ae4f3b6316e60de4e3d9f4dd1f355889f970c (diff)
downloadbcm5719-llvm-7873de0cf65f48e6c8169691ee7eb203b89bfac5.tar.gz
bcm5719-llvm-7873de0cf65f48e6c8169691ee7eb203b89bfac5.zip
P0217R3: Perform semantic checks and initialization for the bindings in a
decomposition declaration for arrays, aggregate-like structs, tuple-like types, and (as an extension) for complex and vector types. llvm-svn: 278435
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp187
1 files changed, 29 insertions, 158 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e850c3c3847..4a68d60a1e2 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -43,7 +43,6 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include <algorithm>
#include <cstring>
@@ -6534,157 +6533,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
return NewVD;
}
-NamedDecl *
-Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
- MultiTemplateParamsArg TemplateParamLists) {
- assert(D.isDecompositionDeclarator());
- const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator();
-
- // The syntax only allows a decomposition declarator as a simple-declaration
- // or a for-range-declaration, but we parse it in more cases than that.
- if (!D.mayHaveDecompositionDeclarator()) {
- Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context)
- << Decomp.getSourceRange();
- return nullptr;
- }
-
- if (!TemplateParamLists.empty()) {
- // FIXME: There's no rule against this, but there are also no rules that
- // would actually make it usable, so we reject it for now.
- Diag(TemplateParamLists.front()->getTemplateLoc(),
- diag::err_decomp_decl_template);
- return nullptr;
- }
-
- Diag(Decomp.getLSquareLoc(), getLangOpts().CPlusPlus1z
- ? diag::warn_cxx14_compat_decomp_decl
- : diag::ext_decomp_decl)
- << Decomp.getSourceRange();
-
- // The semantic context is always just the current context.
- DeclContext *const DC = CurContext;
-
- // C++1z [dcl.dcl]/8:
- // The decl-specifier-seq shall contain only the type-specifier auto
- // and cv-qualifiers.
- auto &DS = D.getDeclSpec();
- {
- SmallVector<StringRef, 8> BadSpecifiers;
- SmallVector<SourceLocation, 8> BadSpecifierLocs;
- if (auto SCS = DS.getStorageClassSpec()) {
- BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS));
- BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc());
- }
- if (auto TSCS = DS.getThreadStorageClassSpec()) {
- BadSpecifiers.push_back(DeclSpec::getSpecifierName(TSCS));
- BadSpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc());
- }
- if (DS.isConstexprSpecified()) {
- BadSpecifiers.push_back("constexpr");
- BadSpecifierLocs.push_back(DS.getConstexprSpecLoc());
- }
- if (DS.isInlineSpecified()) {
- BadSpecifiers.push_back("inline");
- BadSpecifierLocs.push_back(DS.getInlineSpecLoc());
- }
- if (!BadSpecifiers.empty()) {
- auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec);
- Err << (int)BadSpecifiers.size()
- << llvm::join(BadSpecifiers.begin(), BadSpecifiers.end(), " ");
- // Don't add FixItHints to remove the specifiers; we do still respect
- // them when building the underlying variable.
- for (auto Loc : BadSpecifierLocs)
- Err << SourceRange(Loc, Loc);
- }
- // We can't recover from it being declared as a typedef.
- if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
- return nullptr;
- }
-
- TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
- QualType R = TInfo->getType();
-
- if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
- UPPC_DeclarationType))
- D.setInvalidType();
-
- // The syntax only allows a single ref-qualifier prior to the decomposition
- // declarator. No other declarator chunks are permitted. Also check the type
- // specifier here.
- if (DS.getTypeSpecType() != DeclSpec::TST_auto ||
- D.hasGroupingParens() || D.getNumTypeObjects() > 1 ||
- (D.getNumTypeObjects() == 1 &&
- D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) {
- Diag(Decomp.getLSquareLoc(),
- (D.hasGroupingParens() ||
- (D.getNumTypeObjects() &&
- D.getTypeObject(0).Kind == DeclaratorChunk::Paren))
- ? diag::err_decomp_decl_parens
- : diag::err_decomp_decl_type)
- << R;
-
- // In most cases, there's no actual problem with an explicitly-specified
- // type, but a function type won't work here, and ActOnVariableDeclarator
- // shouldn't be called for such a type.
- if (R->isFunctionType())
- D.setInvalidType();
- }
-
- // Build the BindingDecls.
- SmallVector<BindingDecl*, 8> Bindings;
-
- // Build the BindingDecls.
- for (auto &B : D.getDecompositionDeclarator().bindings()) {
- // Check for name conflicts.
- DeclarationNameInfo NameInfo(B.Name, B.NameLoc);
- LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
- ForRedeclaration);
- LookupName(Previous, S,
- /*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit());
-
- // It's not permitted to shadow a template parameter name.
- if (Previous.isSingleResult() &&
- Previous.getFoundDecl()->isTemplateParameter()) {
- DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
- Previous.getFoundDecl());
- Previous.clear();
- }
-
- bool ConsiderLinkage = DC->isFunctionOrMethod() &&
- DS.getStorageClassSpec() == DeclSpec::SCS_extern;
- FilterLookupForScope(Previous, DC, S, ConsiderLinkage,
- /*AllowInlineNamespace*/false);
- if (!Previous.empty()) {
- auto *Old = Previous.getRepresentativeDecl();
- Diag(B.NameLoc, diag::err_redefinition) << B.Name;
- Diag(Old->getLocation(), diag::note_previous_definition);
- }
-
- auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name);
- PushOnScopeChains(BD, S, true);
- Bindings.push_back(BD);
- ParsingInitForAutoVars.insert(BD);
- }
-
- // There are no prior lookup results for the variable itself, because it
- // is unnamed.
- DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr,
- Decomp.getLSquareLoc());
- LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
-
- // Build the variable that holds the non-decomposed object.
- bool AddToScope = true;
- NamedDecl *New =
- ActOnVariableDeclarator(S, D, DC, TInfo, Previous,
- MultiTemplateParamsArg(), AddToScope, Bindings);
- CurContext->addHiddenDecl(New);
-
- if (isInOpenMPDeclareTargetContext())
- checkDeclIsAllowedInOpenMPTarget(nullptr, New);
-
- return New;
-}
-
/// Enum describing the %select options in diag::warn_decl_shadow.
enum ShadowedDeclKind { SDK_Local, SDK_Global, SDK_StaticMember, SDK_Field };
@@ -9604,6 +9452,9 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
assert((!VDecl || !VDecl->isInitCapture()) &&
"init captures are expected to be deduced prior to initialization");
+ // FIXME: Deduction for a decomposition declaration does weird things if the
+ // initializer is an array.
+
ArrayRef<Expr *> DeduceInits = Init;
if (DirectInit) {
if (auto *PL = dyn_cast<ParenListExpr>(Init))
@@ -9713,6 +9564,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
return;
}
+ // C++1z [dcl.dcl]p1 grammar implies that a parenthesized initializer is not
+ // permitted.
+ if (isa<DecompositionDecl>(VDecl) && DirectInit && isa<ParenListExpr>(Init))
+ Diag(VDecl->getLocation(), diag::err_decomp_decl_paren_init) << VDecl;
+
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) {
// Attempt typo correction early so that the type of the init expression can
@@ -9864,8 +9720,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// Perform the initialization.
ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
if (!VDecl->isInvalidDecl()) {
- InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
InitializationKind Kind =
DirectInit
? CXXDirectInit
@@ -10116,7 +9972,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInitStyle(VarDecl::ListInit);
}
- CheckCompleteVariableDeclaration(VDecl);
+ CheckCompleteVariableDeclaration(VDecl, Entity);
}
/// ActOnInitializerError - Given that there was an error parsing an
@@ -10173,6 +10029,13 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
QualType Type = Var->getType();
+ // C++1z [dcl.dcl]p1 grammar implies that an initializer is mandatory.
+ if (isa<DecompositionDecl>(RealDecl)) {
+ Diag(Var->getLocation(), diag::err_decomp_decl_requires_init) << Var;
+ Var->setInvalidDecl();
+ return;
+ }
+
// C++11 [dcl.spec.auto]p3
if (TypeMayContainAuto && Type->getContainedAutoType()) {
Diag(Var->getLocation(), diag::err_auto_var_requires_init)
@@ -10394,7 +10257,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
Var->setInitStyle(VarDecl::CallInit);
}
- CheckCompleteVariableDeclaration(Var);
+ CheckCompleteVariableDeclaration(Var, Entity);
}
}
@@ -10471,7 +10334,8 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
AttrEnd.isValid() ? AttrEnd : IdentLoc);
}
-void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
+void Sema::CheckCompleteVariableDeclaration(VarDecl *var,
+ InitializedEntity &Entity) {
if (var->isInvalidDecl()) return;
if (getLangOpts().OpenCL) {
@@ -10580,6 +10444,9 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
// All the following checks are C++ only.
if (!getLangOpts().CPlusPlus) return;
+ if (auto *DD = dyn_cast<DecompositionDecl>(var))
+ CheckCompleteDecompositionDeclaration(DD, Entity);
+
QualType type = var->getType();
if (type->isDependentType()) return;
@@ -10680,9 +10547,13 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
if (!VD)
return;
- if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl))
- for (auto *BD : DD->bindings())
+ if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl)) {
+ for (auto *BD : DD->bindings()) {
+ if (ThisDecl->isInvalidDecl())
+ BD->setInvalidDecl();
FinalizeDeclaration(BD);
+ }
+ }
checkAttributesAfterMerging(*this, *VD);
OpenPOWER on IntegriCloud