diff options
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 215 |
1 files changed, 95 insertions, 120 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index be1191c..0f96a1c 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -107,6 +107,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_StdCall: \ case AttributeList::AT_ThisCall: \ case AttributeList::AT_Pascal: \ + case AttributeList::AT_VectorCall: \ case AttributeList::AT_MSABI: \ case AttributeList::AT_SysVABI: \ case AttributeList::AT_Regparm: \ @@ -660,26 +661,27 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, // ...and *prepend* it to the declarator. SourceLocation NoLoc; declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction( - /*HasProto=*/true, - /*IsAmbiguous=*/false, - /*LParenLoc=*/NoLoc, - /*ArgInfo=*/nullptr, - /*NumArgs=*/0, - /*EllipsisLoc=*/NoLoc, - /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, - /*RefQualifierIsLvalueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*MutableLoc=*/NoLoc, - EST_None, - /*ESpecLoc=*/NoLoc, - /*Exceptions=*/nullptr, - /*ExceptionRanges=*/nullptr, - /*NumExceptions=*/0, - /*NoexceptExpr=*/nullptr, - loc, loc, declarator)); + /*HasProto=*/true, + /*IsAmbiguous=*/false, + /*LParenLoc=*/NoLoc, + /*ArgInfo=*/nullptr, + /*NumArgs=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLvalueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, + /*MutableLoc=*/NoLoc, EST_None, + /*ESpecLoc=*/NoLoc, + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, + /*NumExceptions=*/0, + /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, + loc, loc, declarator)); // For consistency, make sure the state still has us as processing // the decl spec. @@ -763,7 +765,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // is inferred from the return statements inside the block. // The declspec is always missing in a lambda expr context; it is either // specified with a trailing return type or inferred. - if (S.getLangOpts().CPlusPlus1y && + if (S.getLangOpts().CPlusPlus14 && declarator.getContext() == Declarator::LambdaExprContext) { // In C++1y, a lambda's implicit return type is 'auto'. Result = Context.getAutoDeductType(); @@ -1005,16 +1007,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth; const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size(); const bool IsParameterPack = declarator.hasEllipsis(); - - // Create a name for the invented template parameter type. - std::string InventedTemplateParamName = "$auto-"; - llvm::raw_string_ostream ss(InventedTemplateParamName); - ss << TemplateParameterDepth; - ss << "-" << AutoParameterPosition; - ss.flush(); - - IdentifierInfo& TemplateParamII = Context.Idents.get( - InventedTemplateParamName.c_str()); + // Turns out we must create the TemplateTypeParmDecl here to // retrieve the corresponding template parameter type. TemplateTypeParmDecl *CorrespondingTemplateParam = @@ -1029,11 +1022,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { /*NameLoc*/ declarator.getLocStart(), TemplateParameterDepth, AutoParameterPosition, // our template param index - /* Identifier*/ &TemplateParamII, false, IsParameterPack); + /* Identifier*/ nullptr, false, IsParameterPack); LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam); // Replace the 'auto' in the function parameter with this invented // template type parameter. - Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0); + Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0); } else { Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false); } @@ -1107,8 +1100,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers) << Result << DS.getSourceRange(); else if (TypeQuals & DeclSpec::TQ_volatile) - S.Diag(DS.getVolatileSpecLoc(), diag::warn_typecheck_function_qualifiers) - << Result << DS.getSourceRange(); + S.Diag(DS.getVolatileSpecLoc(), + diag::warn_typecheck_function_qualifiers) + << Result << DS.getSourceRange(); else { assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) && "Has CVRA quals but not C, V, R, or A?"); @@ -1174,6 +1168,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Qualified; } + assert(!Result.isNull() && "This function should not return a null type"); return Result; } @@ -1186,6 +1181,9 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) { QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs, const DeclSpec *DS) { + if (T.isNull()) + return QualType(); + // Enforce C99 6.7.3p2: "Types other than pointer types derived from // object or incomplete types shall not be restrict-qualified." if (Qs.hasRestrict()) { @@ -1224,6 +1222,9 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA, const DeclSpec *DS) { + if (T.isNull()) + return QualType(); + // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic. unsigned CVR = CVRA & ~DeclSpec::TQ_atomic; @@ -1746,7 +1747,7 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) { } // Functions cannot return half FP. - if (T->isHalfType()) { + if (T->isHalfType() && !getLangOpts().HalfArgsAndReturns) { Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 << FixItHint::CreateInsertion(Loc, "*"); return true; @@ -1776,7 +1777,7 @@ QualType Sema::BuildFunctionType(QualType T, if (ParamType->isVoidType()) { Diag(Loc, diag::err_param_with_void_type); Invalid = true; - } else if (ParamType->isHalfType()) { + } else if (ParamType->isHalfType() && !getLangOpts().HalfArgsAndReturns) { // Disallow half FP arguments. Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 << FixItHint::CreateInsertion(Loc, "*"); @@ -2175,7 +2176,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, Error = 0; break; case Declarator::LambdaExprParameterContext: - if (!(SemaRef.getLangOpts().CPlusPlus1y + if (!(SemaRef.getLangOpts().CPlusPlus14 && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto)) Error = 14; break; @@ -2208,11 +2209,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, Error = 10; // Type alias break; case Declarator::TrailingReturnContext: - if (!SemaRef.getLangOpts().CPlusPlus1y) + if (!SemaRef.getLangOpts().CPlusPlus14) Error = 11; // Function return type break; case Declarator::ConversionIdContext: - if (!SemaRef.getLangOpts().CPlusPlus1y) + if (!SemaRef.getLangOpts().CPlusPlus14) Error = 12; // conversion-type-id break; case Declarator::TypeNameContext: @@ -2332,6 +2333,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, } } + assert(!T.isNull() && "This function should not return a null type"); return T; } @@ -2481,7 +2483,8 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { - + // The TypeSourceInfo that this function returns will not be a null type. + // If there is an error, this function will fill in a dummy type as fallback. QualType T = declSpecType; Declarator &D = state.getDeclarator(); Sema &S = state.getSema(); @@ -2697,7 +2700,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // and not, for instance, a pointer to a function. if (D.getDeclSpec().containsPlaceholderType() && !FTI.hasTrailingReturnType() && chunkIndex == 0 && - !S.getLangOpts().CPlusPlus1y) { + !S.getLangOpts().CPlusPlus14) { S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto ? diag::err_auto_missing_trailing_return @@ -2751,7 +2754,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, S.Diag(D.getIdentifierLoc(), diag::err_opencl_half_return) << T; D.setInvalidType(true); } - } else { + } else if (!S.getLangOpts().HalfArgsAndReturns) { S.Diag(D.getIdentifierLoc(), diag::err_parameters_retval_cannot_have_fp16_type) << 1; D.setInvalidType(true); @@ -2941,7 +2944,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, D.setInvalidType(); Param->setInvalidDecl(); } - } else { + } else if (!S.getLangOpts().HalfArgsAndReturns) { S.Diag(Param->getLocation(), diag::err_parameters_retval_cannot_have_fp16_type) << 0; D.setInvalidType(); @@ -2989,12 +2992,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, NoexceptExpr = FTI.NoexceptExpr; } - S.checkExceptionSpecification(FTI.getExceptionSpecType(), + S.checkExceptionSpecification(D.isFunctionDeclarationContext(), + FTI.getExceptionSpecType(), DynamicExceptions, DynamicExceptionRanges, NoexceptExpr, Exceptions, - EPI); + EPI.ExceptionSpec); T = Context.getFunctionType(T, ParamTys, EPI); } @@ -3021,6 +3025,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: llvm_unreachable("Nested-name-specifier must name a type"); case NestedNameSpecifier::TypeSpec: @@ -3044,7 +3049,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } if (!ClsType.isNull()) - T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier()); + T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc, + D.getIdentifier()); if (T.isNull()) { T = Context.IntTy; D.setInvalidType(true); @@ -3064,6 +3070,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, processTypeAttrs(state, T, TAL_DeclChunk, attrs); } + assert(!T.isNull() && "T must not be null after this point"); + if (LangOpts.CPlusPlus && T->isFunctionType()) { const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>(); assert(FnTy && "Why oh why is there not a FunctionProtoType here?"); @@ -3120,9 +3128,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc()); if (Chunk.Fun.TypeQuals & Qualifiers::Volatile) RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc()); - // FIXME: We do not track the location of the __restrict qualifier. - //if (Chunk.Fun.TypeQuals & Qualifiers::Restrict) - // RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc()); + if (Chunk.Fun.TypeQuals & Qualifiers::Restrict) + RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc()); if (!RemovalLocs.empty()) { std::sort(RemovalLocs.begin(), RemovalLocs.end(), BeforeThanCompare<SourceLocation>(S.getSourceManager())); @@ -3153,12 +3160,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } // Apply any undistributed attributes from the declarator. - if (!T.isNull()) - if (AttributeList *attrs = D.getAttributes()) - processTypeAttrs(state, T, TAL_DeclName, attrs); + if (AttributeList *attrs = D.getAttributes()) + processTypeAttrs(state, T, TAL_DeclName, attrs); // Diagnose any ignored type attributes. - if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T); + state.diagnoseIgnoredTypeAttrs(T); // C++0x [dcl.constexpr]p9: // A constexpr specifier used in an object declaration declares the object @@ -3169,7 +3175,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // If there was an ellipsis in the declarator, the declaration declares a // parameter pack whose type may be a pack expansion type. - if (D.hasEllipsis() && !T.isNull()) { + if (D.hasEllipsis()) { // C++0x [dcl.fct]p13: // A declarator-id or abstract-declarator containing an ellipsis shall // only be used in a parameter-declaration. Such a parameter-declaration @@ -3234,15 +3240,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case Declarator::TemplateTypeArgContext: // FIXME: We may want to allow parameter packs in block-literal contexts // in the future. - S.Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter); + S.Diag(D.getEllipsisLoc(), + diag::err_ellipsis_in_declarator_not_parameter); D.setEllipsisLoc(SourceLocation()); break; } } - if (T.isNull()) - return Context.getNullTypeSourceInfo(); - else if (D.isInvalidType()) + assert(!T.isNull() && "T must not be null at the end of this function"); + if (D.isInvalidType()) return Context.getTrivialTypeSourceInfo(T); return S.GetTypeSourceInfoForDeclarator(D, T, TInfo); @@ -3261,8 +3267,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { TypeSourceInfo *ReturnTypeInfo = nullptr; QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo); - if (T.isNull()) - return Context.getNullTypeSourceInfo(); if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount) inferARCWriteback(state, T); @@ -3376,8 +3380,6 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) { TypeSourceInfo *ReturnTypeInfo = nullptr; QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo); - if (declSpecTy.isNull()) - return Context.getNullTypeSourceInfo(); if (getLangOpts().ObjCAutoRefCount) { Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy); @@ -3417,6 +3419,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_ThisCall; case AttributedType::attr_pascal: return AttributeList::AT_Pascal; + case AttributedType::attr_vectorcall: + return AttributeList::AT_VectorCall; case AttributedType::attr_pcs: case AttributedType::attr_pcs_vfp: return AttributeList::AT_Pcs; @@ -3717,6 +3721,7 @@ namespace { case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: llvm_unreachable("Nested-name-specifier must name a type"); } @@ -3975,6 +3980,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, ASIdx = LangAS::opencl_local; break; case AttributeList::AT_OpenCLConstantAddressSpace: ASIdx = LangAS::opencl_constant; break; + case AttributeList::AT_OpenCLGenericAddressSpace: + ASIdx = LangAS::opencl_generic; break; default: assert(Attr.getKind() == AttributeList::AT_OpenCLPrivateAddressSpace); ASIdx = 0; break; @@ -4432,6 +4439,8 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { return AttributedType::attr_thiscall; case AttributeList::AT_Pascal: return AttributedType::attr_pascal; + case AttributeList::AT_VectorCall: + return AttributedType::attr_vectorcall; case AttributeList::AT_Pcs: { // The attribute may have had a fixit applied where we treated an // identifier as a string literal. The contents of the string are valid, @@ -4549,7 +4558,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } // Diagnose use of callee-cleanup calling convention on variadic functions. - if (isCalleeCleanup(CC)) { + if (!supportsVariadicCall(CC)) { const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn); if (FnP && FnP->isVariadic()) { unsigned DiagID = diag::err_cconv_varargs; @@ -4564,23 +4573,12 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } } - // Diagnose the use of X86 fastcall on unprototyped functions. - if (CC == CC_X86FastCall) { - if (isa<FunctionNoProtoType>(fn)) { - S.Diag(attr.getLoc(), diag::err_cconv_knr) - << FunctionType::getNameForCallConv(CC); - attr.setInvalid(); - return true; - } - - // Also diagnose fastcall with regparm. - if (fn->getHasRegParm()) { - S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) - << "regparm" - << FunctionType::getNameForCallConv(CC); - attr.setInvalid(); - return true; - } + // Also diagnose fastcall with regparm. + if (CC == CC_X86FastCall && fn->getHasRegParm()) { + S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) + << "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall); + attr.setInvalid(); + return true; } // Modify the CC from the wrapped function type, wrap it all back, and then @@ -4739,9 +4737,7 @@ static bool isPermittedNeonBaseType(QualType &Ty, // Signed poly is mathematically wrong, but has been baked into some ABIs by // now. bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 || - Triple.getArch() == llvm::Triple::aarch64_be || - Triple.getArch() == llvm::Triple::arm64 || - Triple.getArch() == llvm::Triple::arm64_be; + Triple.getArch() == llvm::Triple::aarch64_be; if (VecKind == VectorType::NeonPolyVector) { if (IsPolyUnsigned) { // AArch64 polynomial vectors are unsigned and support poly64. @@ -4759,9 +4755,7 @@ static bool isPermittedNeonBaseType(QualType &Ty, // Non-polynomial vector types: the usual suspects are allowed, as well as // float64_t on AArch64. bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 || - Triple.getArch() == llvm::Triple::aarch64_be || - Triple.getArch() == llvm::Triple::arm64 || - Triple.getArch() == llvm::Triple::arm64_be; + Triple.getArch() == llvm::Triple::aarch64_be; if (Is64Bit && BTy->getKind() == BuiltinType::Double) return true; @@ -4899,6 +4893,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, case AttributeList::AT_OpenCLGlobalAddressSpace: case AttributeList::AT_OpenCLLocalAddressSpace: case AttributeList::AT_OpenCLConstantAddressSpace: + case AttributeList::AT_OpenCLGenericAddressSpace: case AttributeList::AT_AddressSpace: HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); @@ -5098,31 +5093,9 @@ static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) { // If this definition was instantiated from a template, map back to the // pattern from which it was instantiated. - // - // FIXME: There must be a better place for this to live. if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { - if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { - auto From = TD->getInstantiatedFrom(); - if (auto *CTD = From.dyn_cast<ClassTemplateDecl*>()) { - while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) { - if (NewCTD->isMemberSpecialization()) - break; - CTD = NewCTD; - } - RD = CTD->getTemplatedDecl(); - } else if (auto *CTPSD = From.dyn_cast< - ClassTemplatePartialSpecializationDecl *>()) { - while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) { - if (NewCTPSD->isMemberSpecialization()) - break; - CTPSD = NewCTPSD; - } - RD = CTPSD; - } - } else if (isTemplateInstantiation(RD->getTemplateSpecializationKind())) { - while (auto *NewRD = RD->getInstantiatedFromMemberClass()) - RD = NewRD; - } + if (auto *Pattern = RD->getTemplateInstantiationPattern()) + RD = Pattern; D = RD->getDefinition(); } else if (auto *ED = dyn_cast<EnumDecl>(D)) { while (auto *NewED = ED->getInstantiatedFromMemberEnum()) @@ -5178,14 +5151,6 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { ? S.ImplicitMSInheritanceAttrLoc : RD->getSourceRange())); } - - if (RD->hasDefinition()) { - // Assign inheritance models to all of the base classes, because now we can - // form pointers to members of base classes without calling - // RequireCompleteType on the pointer to member of the base class type. - for (const CXXBaseSpecifier &BS : RD->bases()) - assignInheritanceModel(S, BS.getType()->getAsCXXRecordDecl()); - } } /// \brief The implementation of RequireCompleteType @@ -5510,6 +5475,8 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { } else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) { if (PR->isExplicitProperty()) return PR->getExplicitProperty()->getType(); + } else if (auto *PE = dyn_cast<PredefinedExpr>(E)) { + return PE->getType(); } // C++11 [expr.lambda.prim]p18: @@ -5550,11 +5517,19 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { return T; } -QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) { +QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc, + bool AsUnevaluated) { ExprResult ER = CheckPlaceholderExpr(E); if (ER.isInvalid()) return QualType(); E = ER.get(); + if (AsUnevaluated && ActiveTemplateInstantiations.empty() && + E->HasSideEffects(Context, false)) { + // The expression operand for decltype is in an unevaluated expression + // context, so side effects could result in unintended consequences. + Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context); + } + return Context.getDecltypeType(E, getDecltypeForExpr(*this, E)); } |