diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 403 |
1 files changed, 256 insertions, 147 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 62ec83967bff..507e4a6cd436 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -867,6 +867,9 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); LookupParsedName(Result, S, &SS, !CurMethod); + if (SS.isInvalid()) + return NameClassification::Error(); + // For unqualified lookup in a class template in MSVC mode, look into // dependent base classes where the primary class template is known. if (Result.empty() && SS.isEmpty() && getLangOpts().MSVCCompat) { @@ -879,7 +882,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, // synthesized instance variables), if we're in an Objective-C method. // FIXME: This lookup really, really needs to be folded in to the normal // unqualified lookup mechanism. - if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { + if (SS.isEmpty() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { DeclResult Ivar = LookupIvarInObjCMethod(Result, S, Name); if (Ivar.isInvalid()) return NameClassification::Error(); @@ -899,7 +902,7 @@ Corrected: case LookupResult::NotFound: // If an unqualified-id is followed by a '(', then we have a function // call. - if (!SS.isSet() && NextToken.is(tok::l_paren)) { + if (SS.isEmpty() && NextToken.is(tok::l_paren)) { // In C++, this is an ADL-only call. // FIXME: Reference? if (getLangOpts().CPlusPlus) @@ -921,7 +924,7 @@ Corrected: return NameClassification::NonType(D); } - if (getLangOpts().CPlusPlus2a && !SS.isSet() && NextToken.is(tok::less)) { + if (getLangOpts().CPlusPlus2a && SS.isEmpty() && NextToken.is(tok::less)) { // In C++20 onwards, this could be an ADL-only call to a function // template, and we're required to assume that this is a template name. // @@ -1063,7 +1066,7 @@ Corrected: hasAnyAcceptableTemplateNames( Result, /*AllowFunctionTemplates=*/true, /*AllowDependent=*/false, - /*AllowNonTemplateFunctions*/ !SS.isSet() && + /*AllowNonTemplateFunctions*/ SS.isEmpty() && getLangOpts().CPlusPlus2a))) { // C++ [temp.names]p3: // After name lookup (3.4) finds that a name is a template-name or that @@ -1092,7 +1095,7 @@ Corrected: IsFunctionTemplate = isa<FunctionTemplateDecl>(TD); IsVarTemplate = isa<VarTemplateDecl>(TD); - if (SS.isSet() && !SS.isInvalid()) + if (SS.isNotEmpty()) Template = Context.getQualifiedTemplateName(SS.getScopeRep(), /*TemplateKeyword=*/false, TD); @@ -1802,6 +1805,13 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { (VD->getInit()->isValueDependent() || !VD->evaluateValue())) return false; } + + // Suppress the warning if we don't know how this is constructed, and + // it could possibly be non-trivial constructor. + if (Init->isTypeDependent()) + for (const CXXConstructorDecl *Ctor : RD->ctors()) + if (!Ctor->isTrivial()) + return false; } } } @@ -2549,7 +2559,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, NewAttr = S.mergeCodeSegAttr(D, *CSA, CSA->getName()); else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr)) NewAttr = S.mergeMSInheritanceAttr(D, *IA, IA->getBestCase(), - IA->getSemanticSpelling()); + IA->getInheritanceModel()); else if (const auto *AA = dyn_cast<AlwaysInlineAttr>(Attr)) NewAttr = S.mergeAlwaysInlineAttr(D, *AA, &S.Context.Idents.get(AA->getSpelling())); @@ -2675,6 +2685,10 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { // C's _Noreturn is allowed to be added to a function after it is defined. ++I; continue; + } else if (isa<UuidAttr>(NewAttribute)) { + // msvc will allow a subsequent definition to add an uuid to a class + ++I; + continue; } else if (const AlignedAttr *AA = dyn_cast<AlignedAttr>(NewAttribute)) { if (AA->isAlignas()) { // C++11 [dcl.align]p6: @@ -2993,28 +3007,6 @@ struct GNUCompatibleParamWarning { } // end anonymous namespace -/// getSpecialMember - get the special member enum for a method. -Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { - if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { - if (Ctor->isDefaultConstructor()) - return Sema::CXXDefaultConstructor; - - if (Ctor->isCopyConstructor()) - return Sema::CXXCopyConstructor; - - if (Ctor->isMoveConstructor()) - return Sema::CXXMoveConstructor; - } else if (isa<CXXDestructorDecl>(MD)) { - return Sema::CXXDestructor; - } else if (MD->isCopyAssignmentOperator()) { - return Sema::CXXCopyAssignment; - } else if (MD->isMoveAssignmentOperator()) { - return Sema::CXXMoveAssignment; - } - - return Sema::CXXInvalid; -} - // Determine whether the previous declaration was a definition, implicit // declaration, or a declaration. template <typename T> @@ -3668,6 +3660,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); } + // Check if the function types are compatible when pointer size address + // spaces are ignored. + if (Context.hasSameFunctionTypeIgnoringPtrSizes(OldQType, NewQType)) + return false; + // GNU C permits a K&R definition to follow a prototype declaration // if the declared types of the parameters in the K&R definition // match the types in the prototype declaration, even when the @@ -5032,6 +5029,8 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, /*BitWidth=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); Anon->setAccess(AS); + ProcessDeclAttributes(S, Anon, Dc); + if (getLangOpts().CPlusPlus) FieldCollector->Add(cast<FieldDecl>(Anon)); } else { @@ -5045,6 +5044,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, SC = SC_None; } + assert(DS.getAttributes().empty() && "No attribute expected"); Anon = VarDecl::Create(Context, Owner, DS.getBeginLoc(), Record->getLocation(), /*IdentifierInfo=*/nullptr, Context.getTypeDeclType(Record), TInfo, SC); @@ -6139,6 +6139,41 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) { return false; } +void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) { + if (Decl->getType().hasAddressSpace()) + return; + if (VarDecl *Var = dyn_cast<VarDecl>(Decl)) { + QualType Type = Var->getType(); + if (Type->isSamplerT() || Type->isVoidType()) + return; + LangAS ImplAS = LangAS::opencl_private; + if ((getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) && + Var->hasGlobalStorage()) + ImplAS = LangAS::opencl_global; + // If the original type from a decayed type is an array type and that array + // type has no address space yet, deduce it now. + if (auto DT = dyn_cast<DecayedType>(Type)) { + auto OrigTy = DT->getOriginalType(); + if (!OrigTy.hasAddressSpace() && OrigTy->isArrayType()) { + // Add the address space to the original array type and then propagate + // that to the element type through `getAsArrayType`. + OrigTy = Context.getAddrSpaceQualType(OrigTy, ImplAS); + OrigTy = QualType(Context.getAsArrayType(OrigTy), 0); + // Re-generate the decayed type. + Type = Context.getDecayedType(OrigTy); + } + } + Type = Context.getAddrSpaceQualType(Type, ImplAS); + // Apply any qualifiers (including address space) from the array type to + // the element type. This implements C99 6.7.3p8: "If the specification of + // an array type includes any type qualifiers, the element type is so + // qualified, not the array type." + if (Type->isArrayType()) + Type = QualType(Context.getAsArrayType(Type), 0); + Decl->setType(Type); + } +} + static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { // Ensure that an auto decl is deduced otherwise the checks below might cache // the wrong linkage. @@ -6496,6 +6531,105 @@ static bool isDeclExternC(const Decl *D) { llvm_unreachable("Unknown type of decl!"); } +/// Returns true if there hasn't been any invalid type diagnosed. +static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D, + DeclContext *DC, QualType R) { + // OpenCL v2.0 s6.9.b - Image type can only be used as a function argument. + // OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function + // argument. + if (R->isImageType() || R->isPipeType()) { + Se.Diag(D.getIdentifierLoc(), + diag::err_opencl_type_can_only_be_used_as_function_parameter) + << R; + D.setInvalidType(); + return false; + } + + // OpenCL v1.2 s6.9.r: + // The event type cannot be used to declare a program scope variable. + // OpenCL v2.0 s6.9.q: + // The clk_event_t and reserve_id_t types cannot be declared in program + // scope. + if (NULL == S->getParent()) { + if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) { + Se.Diag(D.getIdentifierLoc(), + diag::err_invalid_type_for_program_scope_var) + << R; + D.setInvalidType(); + return false; + } + } + + // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed. + QualType NR = R; + while (NR->isPointerType()) { + if (NR->isFunctionPointerType()) { + Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); + D.setInvalidType(); + return false; + } + NR = NR->getPointeeType(); + } + + if (!Se.getOpenCLOptions().isEnabled("cl_khr_fp16")) { + // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and + // half array type (unless the cl_khr_fp16 extension is enabled). + if (Se.Context.getBaseElementType(R)->isHalfType()) { + Se.Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R; + D.setInvalidType(); + return false; + } + } + + // OpenCL v1.2 s6.9.r: + // The event type cannot be used with the __local, __constant and __global + // address space qualifiers. + if (R->isEventT()) { + if (R.getAddressSpace() != LangAS::opencl_private) { + Se.Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual); + D.setInvalidType(); + return false; + } + } + + // C++ for OpenCL does not allow the thread_local storage qualifier. + // OpenCL C does not support thread_local either, and + // also reject all other thread storage class specifiers. + DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec(); + if (TSC != TSCS_unspecified) { + bool IsCXX = Se.getLangOpts().OpenCLCPlusPlus; + Se.Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_opencl_unknown_type_specifier) + << IsCXX << Se.getLangOpts().getOpenCLVersionTuple().getAsString() + << DeclSpec::getSpecifierName(TSC) << 1; + D.setInvalidType(); + return false; + } + + if (R->isSamplerT()) { + // OpenCL v1.2 s6.9.b p4: + // The sampler type cannot be used with the __local and __global address + // space qualifiers. + if (R.getAddressSpace() == LangAS::opencl_local || + R.getAddressSpace() == LangAS::opencl_global) { + Se.Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace); + D.setInvalidType(); + } + + // OpenCL v1.2 s6.12.14.1: + // A global sampler must be declared with either the constant address + // space qualifier or with the const qualifier. + if (DC->isTranslationUnit() && + !(R.getAddressSpace() == LangAS::opencl_constant || + R.isConstQualified())) { + Se.Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler); + D.setInvalidType(); + } + if (D.isInvalidType()) + return false; + } + return true; +} NamedDecl *Sema::ActOnVariableDeclarator( Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, @@ -6519,95 +6653,6 @@ NamedDecl *Sema::ActOnVariableDeclarator( return nullptr; } - if (getLangOpts().OpenCL) { - // OpenCL v2.0 s6.9.b - Image type can only be used as a function argument. - // OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function - // argument. - if (R->isImageType() || R->isPipeType()) { - Diag(D.getIdentifierLoc(), - diag::err_opencl_type_can_only_be_used_as_function_parameter) - << R; - D.setInvalidType(); - return nullptr; - } - - // OpenCL v1.2 s6.9.r: - // The event type cannot be used to declare a program scope variable. - // OpenCL v2.0 s6.9.q: - // The clk_event_t and reserve_id_t types cannot be declared in program scope. - if (NULL == S->getParent()) { - if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) { - Diag(D.getIdentifierLoc(), - diag::err_invalid_type_for_program_scope_var) << R; - D.setInvalidType(); - return nullptr; - } - } - - // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed. - QualType NR = R; - while (NR->isPointerType()) { - if (NR->isFunctionPointerType()) { - Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); - D.setInvalidType(); - break; - } - NR = NR->getPointeeType(); - } - - if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) { - // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and - // half array type (unless the cl_khr_fp16 extension is enabled). - if (Context.getBaseElementType(R)->isHalfType()) { - Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R; - D.setInvalidType(); - } - } - - if (R->isSamplerT()) { - // OpenCL v1.2 s6.9.b p4: - // The sampler type cannot be used with the __local and __global address - // space qualifiers. - if (R.getAddressSpace() == LangAS::opencl_local || - R.getAddressSpace() == LangAS::opencl_global) { - Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace); - } - - // OpenCL v1.2 s6.12.14.1: - // A global sampler must be declared with either the constant address - // space qualifier or with the const qualifier. - if (DC->isTranslationUnit() && - !(R.getAddressSpace() == LangAS::opencl_constant || - R.isConstQualified())) { - Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler); - D.setInvalidType(); - } - } - - // OpenCL v1.2 s6.9.r: - // The event type cannot be used with the __local, __constant and __global - // address space qualifiers. - if (R->isEventT()) { - if (R.getAddressSpace() != LangAS::opencl_private) { - Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual); - D.setInvalidType(); - } - } - - // C++ for OpenCL does not allow the thread_local storage qualifier. - // OpenCL C does not support thread_local either, and - // also reject all other thread storage class specifiers. - DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec(); - if (TSC != TSCS_unspecified) { - bool IsCXX = getLangOpts().OpenCLCPlusPlus; - Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), - diag::err_opencl_unknown_type_specifier) - << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString() - << DeclSpec::getSpecifierName(TSC) << 1; - D.setInvalidType(); - return nullptr; - } - } DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec()); @@ -6964,6 +7009,13 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } + if (getLangOpts().OpenCL) { + + deduceOpenCLAddressSpace(NewVD); + + diagnoseOpenCLTypes(S, *this, D, DC, NewVD->getType()); + } + // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewVD, D); @@ -7039,8 +7091,9 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } - NewVD->addAttr(::new (Context) AsmLabelAttr( - Context, SE->getStrTokenLoc(0), Label, /*IsLiteralLabel=*/true)); + NewVD->addAttr(AsmLabelAttr::Create(Context, Label, + /*IsLiteralLabel=*/true, + SE->getStrTokenLoc(0))); } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I = ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier()); @@ -7842,7 +7895,13 @@ struct FindOverriddenMethod { Path.Decls = Path.Decls.slice(1)) { NamedDecl *D = Path.Decls.front(); if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - if (MD->isVirtual() && !S->IsOverload(Method, MD, false)) + if (MD->isVirtual() && + !S->IsOverload( + Method, MD, /*UseMemberUsingDeclRules=*/false, + /*ConsiderCudaAttrs=*/true, + // C++2a [class.virtual]p2 does not consider requires clauses + // when overriding. + /*ConsiderRequiresClauses=*/false)) return true; } } @@ -8187,7 +8246,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, isInline, HasPrototype, - CSK_unspecified); + CSK_unspecified, + /*TrailingRequiresClause=*/nullptr); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -8204,6 +8264,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, ConstexprKind = CSK_unspecified; D.getMutableDeclSpec().ClearConstexprSpec(); } + Expr *TrailingRequiresClause = D.getTrailingRequiresClause(); // Check that the return type is not an abstract class type. // For record types, this is done by the AbstractClassUsageDiagnoser once @@ -8223,7 +8284,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, return CXXConstructorDecl::Create( SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, TInfo, ExplicitSpecifier, isInline, - /*isImplicitlyDeclared=*/false, ConstexprKind); + /*isImplicitlyDeclared=*/false, ConstexprKind, InheritedConstructor(), + TrailingRequiresClause); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. @@ -8232,8 +8294,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); CXXDestructorDecl *NewDD = CXXDestructorDecl::Create( SemaRef.Context, Record, D.getBeginLoc(), NameInfo, R, TInfo, - isInline, - /*isImplicitlyDeclared=*/false, ConstexprKind); + isInline, /*isImplicitlyDeclared=*/false, ConstexprKind, + TrailingRequiresClause); // If the destructor needs an implicit exception specification, set it // now. FIXME: It'd be nice to be able to create the right type to start @@ -8253,7 +8315,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), Name, R, TInfo, SC, isInline, - /*hasPrototype=*/true, ConstexprKind); + /*hasPrototype=*/true, ConstexprKind, + TrailingRequiresClause); } } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { @@ -8270,9 +8333,14 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, IsVirtualOkay = true; return CXXConversionDecl::Create( SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, - TInfo, isInline, ExplicitSpecifier, ConstexprKind, SourceLocation()); + TInfo, isInline, ExplicitSpecifier, ConstexprKind, SourceLocation(), + TrailingRequiresClause); } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { + if (TrailingRequiresClause) + SemaRef.Diag(TrailingRequiresClause->getBeginLoc(), + diag::err_trailing_requires_clause_on_deduction_guide) + << TrailingRequiresClause->getSourceRange(); SemaRef.CheckDeductionGuideDeclarator(D, R, SC); return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), @@ -8294,7 +8362,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // This is a C++ method declaration. CXXMethodDecl *Ret = CXXMethodDecl::Create( SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, - TInfo, SC, isInline, ConstexprKind, SourceLocation()); + TInfo, SC, isInline, ConstexprKind, SourceLocation(), + TrailingRequiresClause); IsVirtualOkay = !Ret->isStatic(); return Ret; } else { @@ -8308,7 +8377,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // - we're in C++ (where every function has a prototype), return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, isInline, true /*HasPrototype*/, - ConstexprKind); + ConstexprKind, TrailingRequiresClause); } } @@ -8332,7 +8401,7 @@ static bool isOpenCLSizeDependentType(ASTContext &C, QualType Ty) { QualType DesugaredTy = Ty; do { ArrayRef<StringRef> Names(SizeTypeNames); - auto Match = llvm::find(Names, DesugaredTy.getAsString()); + auto Match = llvm::find(Names, DesugaredTy.getUnqualifiedType().getAsString()); if (Names.end() != Match) return true; @@ -8943,9 +9012,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewFD->addAttr(::new (Context) - AsmLabelAttr(Context, SE->getStrTokenLoc(0), - SE->getString(), /*IsLiteralLabel=*/true)); + NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(), + /*IsLiteralLabel=*/true, + SE->getStrTokenLoc(0))); } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I = ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier()); @@ -9551,6 +9620,29 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + // Diagnose no_builtin attribute on function declaration that are not a + // definition. + // FIXME: We should really be doing this in + // SemaDeclAttr.cpp::handleNoBuiltinAttr, unfortunately we only have access to + // the FunctionDecl and at this point of the code + // FunctionDecl::isThisDeclarationADefinition() which always returns `false` + // because Sema::ActOnStartOfFunctionDef has not been called yet. + if (const auto *NBA = NewFD->getAttr<NoBuiltinAttr>()) + switch (D.getFunctionDefinitionKind()) { + case FDK_Defaulted: + case FDK_Deleted: + Diag(NBA->getLocation(), + diag::err_attribute_no_builtin_on_defaulted_deleted_function) + << NBA->getSpelling(); + break; + case FDK_Declaration: + Diag(NBA->getLocation(), diag::err_attribute_no_builtin_on_non_definition) + << NBA->getSpelling(); + break; + case FDK_Definition: + break; + } + return NewFD; } @@ -9687,7 +9779,7 @@ bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) { static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) { const auto *TA = FD->getAttr<TargetAttr>(); assert(TA && "MultiVersion Candidate requires a target attribute"); - TargetAttr::ParsedTargetAttr ParseInfo = TA->parse(); + ParsedTargetAttr ParseInfo = TA->parse(); const TargetInfo &TargetInfo = S.Context.getTargetInfo(); enum ErrType { Feature = 0, Architecture = 1 }; @@ -9764,13 +9856,15 @@ bool Sema::areMultiversionVariantFunctionsCompatible( Linkage = 5, }; - if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) { + if (NoProtoDiagID.getDiagID() != 0 && OldFD && + !OldFD->getType()->getAs<FunctionProtoType>()) { Diag(OldFD->getLocation(), NoProtoDiagID); Diag(NoteCausedDiagIDAt.first, NoteCausedDiagIDAt.second); return true; } - if (!NewFD->getType()->getAs<FunctionProtoType>()) + if (NoProtoDiagID.getDiagID() != 0 && + !NewFD->getType()->getAs<FunctionProtoType>()) return Diag(NewFD->getLocation(), NoProtoDiagID); if (!TemplatesSupported && @@ -9938,7 +10032,7 @@ static bool CheckTargetCausesMultiVersioning( bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious, LookupResult &Previous) { const auto *OldTA = OldFD->getAttr<TargetAttr>(); - TargetAttr::ParsedTargetAttr NewParsed = NewTA->parse(); + ParsedTargetAttr NewParsed = NewTA->parse(); // Sort order doesn't matter, it just needs to be consistent. llvm::sort(NewParsed.Features); @@ -9982,8 +10076,7 @@ static bool CheckTargetCausesMultiVersioning( return true; } - TargetAttr::ParsedTargetAttr OldParsed = - OldTA->parse(std::less<std::string>()); + ParsedTargetAttr OldParsed = OldTA->parse(std::less<std::string>()); if (OldParsed == NewParsed) { S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); @@ -10036,7 +10129,7 @@ static bool CheckMultiVersionAdditionalDecl( return true; } - TargetAttr::ParsedTargetAttr NewParsed; + ParsedTargetAttr NewParsed; if (NewTA) { NewParsed = NewTA->parse(); llvm::sort(NewParsed.Features); @@ -10063,8 +10156,7 @@ static bool CheckMultiVersionAdditionalDecl( return false; } - TargetAttr::ParsedTargetAttr CurParsed = - CurTA->parse(std::less<std::string>()); + ParsedTargetAttr CurParsed = CurTA->parse(std::less<std::string>()); if (CurParsed == NewParsed) { S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); S.Diag(CurFD->getLocation(), diag::note_previous_declaration); @@ -10496,6 +10588,11 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } } } + if (Method->isVirtual() && NewFD->getTrailingRequiresClause()) + // C++2a [class.virtual]p6 + // A virtual method shall not have a requires-clause. + Diag(NewFD->getTrailingRequiresClause()->getBeginLoc(), + diag::err_constrained_virtual_method); if (Method->isStatic()) checkThisInStaticMemberFunctionType(Method); @@ -11281,6 +11378,9 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) VDecl->setInvalidDecl(); + if (getLangOpts().OpenCL) + deduceOpenCLAddressSpace(VDecl); + // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. if (VarDecl *Old = VDecl->getPreviousDecl()) { @@ -12145,6 +12245,10 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { Diag(Var->getLocation(), diag::note_private_extern); } + if (Context.getTargetInfo().allowDebugInfoForExternalVar() && + !Var->isInvalidDecl() && !getLangOpts().CPlusPlus) + ExternalDeclarations.push_back(Var); + return; case VarDecl::TentativeDefinition: @@ -13103,6 +13207,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (New->hasAttr<BlocksAttr>()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); } + + if (getLangOpts().OpenCL) + deduceOpenCLAddressSpace(New); + return New; } @@ -13315,8 +13423,10 @@ ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, return false; // Don't warn about 'main'. - if (FD->isMain()) - return false; + if (isa<TranslationUnitDecl>(FD->getDeclContext()->getRedeclContext())) + if (IdentifierInfo *II = FD->getIdentifier()) + if (II->isStr("main")) + return false; // Don't warn about inline functions. if (FD->isInlined()) @@ -13826,8 +13936,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, LSI->ReturnType.isNull() ? Context.VoidTy : LSI->ReturnType; // Update the return type to the deduced type. - const FunctionProtoType *Proto = - FD->getType()->getAs<FunctionProtoType>(); + const auto *Proto = FD->getType()->castAs<FunctionProtoType>(); FD->setType(Context.getFunctionType(RetType, Proto->getParamTypes(), Proto->getExtProtoInfo())); } @@ -16031,7 +16140,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } // TR 18037 does not allow fields to be declared with address space - if (T.getQualifiers().hasAddressSpace() || T->isDependentAddressSpaceType() || + if (T.hasAddressSpace() || T->isDependentAddressSpaceType() || T->getBaseElementTypeUnsafe()->isDependentAddressSpaceType()) { Diag(Loc, diag::err_field_with_address_space); Record->setInvalidDecl(); @@ -16754,7 +16863,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (const MSInheritanceAttr *IA = Record->getAttr<MSInheritanceAttr>()) checkMSInheritanceAttrOnDefinition(cast<CXXRecordDecl>(Record), IA->getRange(), IA->getBestCase(), - IA->getSemanticSpelling()); + IA->getInheritanceModel()); } // Check if the structure/union declaration is a type that can have zero |