Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -3250,8 +3250,7 @@ // Make sure that we're referring to a value. if (!isa(D)) { - Diag(Loc, diag::err_ref_non_value) - << D << SS.getRange(); + Diag(Loc, diag::err_ref_non_value) << D << SS.getRange(); Diag(D->getLocation(), diag::note_declared_at); return ExprError(); } @@ -3277,210 +3276,204 @@ return BuildAnonymousStructUnionMemberReference(SS, NameInfo.getLoc(), indirectField); - { - QualType type = VD->getType(); - if (type.isNull()) - return ExprError(); - ExprValueKind valueKind = VK_PRValue; + QualType type = VD->getType(); + if (type.isNull()) + return ExprError(); + ExprValueKind valueKind = VK_PRValue; - // In 'T ...V;', the type of the declaration 'V' is 'T...', but the type of - // a reference to 'V' is simply (unexpanded) 'T'. The type, like the value, - // is expanded by some outer '...' in the context of the use. - type = type.getNonPackExpansionType(); + // In 'T ...V;', the type of the declaration 'V' is 'T...', but the type of + // a reference to 'V' is simply (unexpanded) 'T'. The type, like the value, + // is expanded by some outer '...' in the context of the use. + type = type.getNonPackExpansionType(); - switch (D->getKind()) { + switch (D->getKind()) { // Ignore all the non-ValueDecl kinds. #define ABSTRACT_DECL(kind) #define VALUE(type, base) -#define DECL(type, base) \ - case Decl::type: +#define DECL(type, base) case Decl::type: #include "clang/AST/DeclNodes.inc" - llvm_unreachable("invalid value decl kind"); - - // These shouldn't make it here. - case Decl::ObjCAtDefsField: - llvm_unreachable("forming non-member reference to ivar?"); - - // Enum constants are always r-values and never references. - // Unresolved using declarations are dependent. - case Decl::EnumConstant: - case Decl::UnresolvedUsingValue: - case Decl::OMPDeclareReduction: - case Decl::OMPDeclareMapper: - valueKind = VK_PRValue; + llvm_unreachable("invalid value decl kind"); + + // These shouldn't make it here. + case Decl::ObjCAtDefsField: + llvm_unreachable("forming non-member reference to ivar?"); + + // Enum constants are always r-values and never references. + // Unresolved using declarations are dependent. + case Decl::EnumConstant: + case Decl::UnresolvedUsingValue: + case Decl::OMPDeclareReduction: + case Decl::OMPDeclareMapper: + valueKind = VK_PRValue; + break; + + // Fields and indirect fields that got here must be for + // pointer-to-member expressions; we just call them l-values for + // internal consistency, because this subexpression doesn't really + // exist in the high-level semantics. + case Decl::Field: + case Decl::IndirectField: + case Decl::ObjCIvar: + assert(getLangOpts().CPlusPlus && "building reference to field in C?"); + + // These can't have reference type in well-formed programs, but + // for internal consistency we do this anyway. + type = type.getNonReferenceType(); + valueKind = VK_LValue; + break; + + // Non-type template parameters are either l-values or r-values + // depending on the type. + case Decl::NonTypeTemplateParm: { + if (const ReferenceType *reftype = type->getAs()) { + type = reftype->getPointeeType(); + valueKind = VK_LValue; // even if the parameter is an r-value reference break; + } - // Fields and indirect fields that got here must be for - // pointer-to-member expressions; we just call them l-values for - // internal consistency, because this subexpression doesn't really - // exist in the high-level semantics. - case Decl::Field: - case Decl::IndirectField: - case Decl::ObjCIvar: - assert(getLangOpts().CPlusPlus && - "building reference to field in C?"); - - // These can't have reference type in well-formed programs, but - // for internal consistency we do this anyway. - type = type.getNonReferenceType(); + // [expr.prim.id.unqual]p2: + // If the entity is a template parameter object for a template + // parameter of type T, the type of the expression is const T. + // [...] The expression is an lvalue if the entity is a [...] template + // parameter object. + if (type->isRecordType()) { + type = type.getUnqualifiedType().withConst(); valueKind = VK_LValue; break; + } - // Non-type template parameters are either l-values or r-values - // depending on the type. - case Decl::NonTypeTemplateParm: { - if (const ReferenceType *reftype = type->getAs()) { - type = reftype->getPointeeType(); - valueKind = VK_LValue; // even if the parameter is an r-value reference - break; - } - - // [expr.prim.id.unqual]p2: - // If the entity is a template parameter object for a template - // parameter of type T, the type of the expression is const T. - // [...] The expression is an lvalue if the entity is a [...] template - // parameter object. - if (type->isRecordType()) { - type = type.getUnqualifiedType().withConst(); - valueKind = VK_LValue; - break; - } + // For non-references, we need to strip qualifiers just in case + // the template parameter was declared as 'const int' or whatever. + valueKind = VK_PRValue; + type = type.getUnqualifiedType(); + break; + } - // For non-references, we need to strip qualifiers just in case - // the template parameter was declared as 'const int' or whatever. + case Decl::Var: + case Decl::VarTemplateSpecialization: + case Decl::VarTemplatePartialSpecialization: + case Decl::Decomposition: + case Decl::OMPCapturedExpr: + // In C, "extern void blah;" is valid and is an r-value. + if (!getLangOpts().CPlusPlus && !type.hasQualifiers() && + type->isVoidType()) { valueKind = VK_PRValue; - type = type.getUnqualifiedType(); break; } + LLVM_FALLTHROUGH; - case Decl::Var: - case Decl::VarTemplateSpecialization: - case Decl::VarTemplatePartialSpecialization: - case Decl::Decomposition: - case Decl::OMPCapturedExpr: - // In C, "extern void blah;" is valid and is an r-value. - if (!getLangOpts().CPlusPlus && - !type.hasQualifiers() && - type->isVoidType()) { - valueKind = VK_PRValue; - break; - } - LLVM_FALLTHROUGH; - - case Decl::ImplicitParam: - case Decl::ParmVar: { - // These are always l-values. - valueKind = VK_LValue; - type = type.getNonReferenceType(); - - // FIXME: Does the addition of const really only apply in - // potentially-evaluated contexts? Since the variable isn't actually - // captured in an unevaluated context, it seems that the answer is no. - if (!isUnevaluatedContext()) { - QualType CapturedType = getCapturedDeclRefType(cast(VD), Loc); - if (!CapturedType.isNull()) - type = CapturedType; - } - - break; - } + case Decl::ImplicitParam: + case Decl::ParmVar: { + // These are always l-values. + valueKind = VK_LValue; + type = type.getNonReferenceType(); - case Decl::Binding: { - // These are always lvalues. - valueKind = VK_LValue; - type = type.getNonReferenceType(); - // FIXME: Support lambda-capture of BindingDecls, once CWG actually - // decides how that's supposed to work. - auto *BD = cast(VD); - if (BD->getDeclContext() != CurContext) { - auto *DD = dyn_cast_or_null(BD->getDecomposedDecl()); - if (DD && DD->hasLocalStorage()) - diagnoseUncapturableValueReference(*this, Loc, BD, CurContext); - } - break; + // FIXME: Does the addition of const really only apply in + // potentially-evaluated contexts? Since the variable isn't actually + // captured in an unevaluated context, it seems that the answer is no. + if (!isUnevaluatedContext()) { + QualType CapturedType = getCapturedDeclRefType(cast(VD), Loc); + if (!CapturedType.isNull()) + type = CapturedType; } - case Decl::Function: { - if (unsigned BID = cast(VD)->getBuiltinID()) { - if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) { - type = Context.BuiltinFnTy; - valueKind = VK_PRValue; - break; - } - } + break; + } - const FunctionType *fty = type->castAs(); + case Decl::Binding: { + // These are always lvalues. + valueKind = VK_LValue; + type = type.getNonReferenceType(); + // FIXME: Support lambda-capture of BindingDecls, once CWG actually + // decides how that's supposed to work. + auto *BD = cast(VD); + if (BD->getDeclContext() != CurContext) { + auto *DD = dyn_cast_or_null(BD->getDecomposedDecl()); + if (DD && DD->hasLocalStorage()) + diagnoseUncapturableValueReference(*this, Loc, BD, CurContext); + } + break; + } - // If we're referring to a function with an __unknown_anytype - // result type, make the entire expression __unknown_anytype. - if (fty->getReturnType() == Context.UnknownAnyTy) { - type = Context.UnknownAnyTy; + case Decl::Function: { + if (unsigned BID = cast(VD)->getBuiltinID()) { + if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) { + type = Context.BuiltinFnTy; valueKind = VK_PRValue; break; } + } - // Functions are l-values in C++. - if (getLangOpts().CPlusPlus) { - valueKind = VK_LValue; - break; - } + const FunctionType *fty = type->castAs(); - // C99 DR 316 says that, if a function type comes from a - // function definition (without a prototype), that type is only - // used for checking compatibility. Therefore, when referencing - // the function, we pretend that we don't have the full function - // type. - if (!cast(VD)->hasPrototype() && - isa(fty)) - type = Context.getFunctionNoProtoType(fty->getReturnType(), - fty->getExtInfo()); - - // Functions are r-values in C. + // If we're referring to a function with an __unknown_anytype + // result type, make the entire expression __unknown_anytype. + if (fty->getReturnType() == Context.UnknownAnyTy) { + type = Context.UnknownAnyTy; valueKind = VK_PRValue; break; } - case Decl::CXXDeductionGuide: - llvm_unreachable("building reference to deduction guide"); - - case Decl::MSProperty: - case Decl::MSGuid: - case Decl::TemplateParamObject: - // FIXME: Should MSGuidDecl and template parameter objects be subject to - // capture in OpenMP, or duplicated between host and device? + // Functions are l-values in C++. + if (getLangOpts().CPlusPlus) { valueKind = VK_LValue; break; + } - case Decl::CXXMethod: - // If we're referring to a method with an __unknown_anytype - // result type, make the entire expression __unknown_anytype. - // This should only be possible with a type written directly. - if (const FunctionProtoType *proto - = dyn_cast(VD->getType())) - if (proto->getReturnType() == Context.UnknownAnyTy) { - type = Context.UnknownAnyTy; - valueKind = VK_PRValue; - break; - } + // C99 DR 316 says that, if a function type comes from a + // function definition (without a prototype), that type is only + // used for checking compatibility. Therefore, when referencing + // the function, we pretend that we don't have the full function + // type. + if (!cast(VD)->hasPrototype() && isa(fty)) + type = Context.getFunctionNoProtoType(fty->getReturnType(), + fty->getExtInfo()); + + // Functions are r-values in C. + valueKind = VK_PRValue; + break; + } - // C++ methods are l-values if static, r-values if non-static. - if (cast(VD)->isStatic()) { - valueKind = VK_LValue; + case Decl::CXXDeductionGuide: + llvm_unreachable("building reference to deduction guide"); + + case Decl::MSProperty: + case Decl::MSGuid: + case Decl::TemplateParamObject: + // FIXME: Should MSGuidDecl and template parameter objects be subject to + // capture in OpenMP, or duplicated between host and device? + valueKind = VK_LValue; + break; + + case Decl::CXXMethod: + // If we're referring to a method with an __unknown_anytype + // result type, make the entire expression __unknown_anytype. + // This should only be possible with a type written directly. + if (const FunctionProtoType *proto = + dyn_cast(VD->getType())) + if (proto->getReturnType() == Context.UnknownAnyTy) { + type = Context.UnknownAnyTy; + valueKind = VK_PRValue; break; } - LLVM_FALLTHROUGH; - case Decl::CXXConversion: - case Decl::CXXDestructor: - case Decl::CXXConstructor: - valueKind = VK_PRValue; + // C++ methods are l-values if static, r-values if non-static. + if (cast(VD)->isStatic()) { + valueKind = VK_LValue; break; } + LLVM_FALLTHROUGH; - return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD, - /*FIXME: TemplateKWLoc*/ SourceLocation(), - TemplateArgs); + case Decl::CXXConversion: + case Decl::CXXDestructor: + case Decl::CXXConstructor: + valueKind = VK_PRValue; + break; } + + return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD, + /*FIXME: TemplateKWLoc*/ SourceLocation(), + TemplateArgs); } static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,