blob: e41cd5b6653a2068c9c4b14d528bda7023e9cb46 [file] [log] [blame]
//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for expressions.
//
//===----------------------------------------------------------------------===//
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaFixItUtils.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/Support/ConvertUTF.h"
using namespace clang;
using namespace sema;
/// Determine whether the use of this declaration is valid, without
/// emitting diagnostics.
bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) {
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D))
return false;
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted())
return false;
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, SourceLocation(), /*Diagnose*/ false))
return false;
// See if this is an aligned allocation/deallocation function that is
// unavailable.
if (TreatUnavailableAsInvalid &&
isUnavailableAlignedAllocationFunction(*FD))
return false;
}
// See if this function is unavailable.
if (TreatUnavailableAsInvalid && D->getAvailability() == AR_Unavailable &&
cast<Decl>(CurContext)->getAvailability() != AR_Unavailable)
return false;
return true;
}
static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
// Warn if this is used but marked unused.
if (const auto *A = D->getAttr<UnusedAttr>()) {
// [[maybe_unused]] should not diagnose uses, but __attribute__((unused))
// should diagnose them.
if (A->getSemanticSpelling() != UnusedAttr::CXX11_maybe_unused &&
A->getSemanticSpelling() != UnusedAttr::C2x_maybe_unused) {
const Decl *DC = cast_or_null<Decl>(S.getCurObjCLexicalContext());
if (DC && !DC->hasAttr<UnusedAttr>())
S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName();
}
}
}
/// Emit a note explaining that this function is deleted.
void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
assert(Decl->isDeleted());
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
if (Method && Method->isDeleted() && Method->isDefaulted()) {
// If the method was explicitly defaulted, point at that declaration.
if (!Method->isImplicit())
Diag(Decl->getLocation(), diag::note_implicitly_deleted);
// Try to diagnose why this special member function was implicitly
// deleted. This might fail, if that reason no longer applies.
CXXSpecialMember CSM = getSpecialMember(Method);
if (CSM != CXXInvalid)
ShouldDeleteSpecialMember(Method, CSM, nullptr, /*Diagnose=*/true);
return;
}
auto *Ctor = dyn_cast<CXXConstructorDecl>(Decl);
if (Ctor && Ctor->isInheritingConstructor())
return NoteDeletedInheritingConstructor(Ctor);
Diag(Decl->getLocation(), diag::note_availability_specified_here)
<< Decl << 1;
}
/// Determine whether a FunctionDecl was ever declared with an
/// explicit storage class.
static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
for (auto I : D->redecls()) {
if (I->getStorageClass() != SC_None)
return true;
}
return false;
}
/// Check whether we're in an extern inline function and referring to a
/// variable or function with internal linkage (C11 6.7.4p3).
///
/// This is only a warning because we used to silently accept this code, but
/// in many cases it will not behave correctly. This is not enabled in C++ mode
/// because the restriction language is a bit weaker (C++11 [basic.def.odr]p6)
/// and so while there may still be user mistakes, most of the time we can't
/// prove that there are errors.
static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
const NamedDecl *D,
SourceLocation Loc) {
// This is disabled under C++; there are too many ways for this to fire in
// contexts where the warning is a false positive, or where it is technically
// correct but benign.
if (S.getLangOpts().CPlusPlus)
return;
// Check if this is an inlined function or method.
FunctionDecl *Current = S.getCurFunctionDecl();
if (!Current)
return;
if (!Current->isInlined())
return;
if (!Current->isExternallyVisible())
return;
// Check if the decl has internal linkage.
if (D->getFormalLinkage() != InternalLinkage)
return;
// Downgrade from ExtWarn to Extension if
// (1) the supposedly external inline function is in the main file,
// and probably won't be included anywhere else.
// (2) the thing we're referencing is a pure function.
// (3) the thing we're referencing is another inline function.
// This last can give us false negatives, but it's better than warning on
// wrappers for simple C library functions.
const FunctionDecl *UsedFn = dyn_cast<FunctionDecl>(D);
bool DowngradeWarning = S.getSourceManager().isInMainFile(Loc);
if (!DowngradeWarning && UsedFn)
DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr<ConstAttr>();
S.Diag(Loc, DowngradeWarning ? diag::ext_internal_in_extern_inline_quiet
: diag::ext_internal_in_extern_inline)
<< /*IsVar=*/!UsedFn << D;
S.MaybeSuggestAddingStaticToDecl(Current);
S.Diag(D->getCanonicalDecl()->getLocation(), diag::note_entity_declared_at)
<< D;
}
void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
const FunctionDecl *First = Cur->getFirstDecl();
// Suggest "static" on the function, if possible.
if (!hasAnyExplicitStorageClass(First)) {
SourceLocation DeclBegin = First->getSourceRange().getBegin();
Diag(DeclBegin, diag::note_convert_inline_to_static)
<< Cur << FixItHint::CreateInsertion(DeclBegin, "static ");
}
}
/// Determine whether the use of this declaration is valid, and
/// emit any corresponding diagnostics.
///
/// This routine diagnoses various problems with referencing
/// declarations that can occur when using a declaration. For example,
/// it might warn if a deprecated or unavailable declaration is being
/// used, or produce an error (and return true) if a C++0x deleted
/// function is being used.
///
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks,
ObjCInterfaceDecl *ClassReceiver) {
SourceLocation Loc = Locs.front();
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
auto Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
if (Pos != SuppressedDiagnostics.end()) {
for (const PartialDiagnosticAt &Suppressed : Pos->second)
Diag(Suppressed.first, Suppressed.second);
// Clear out the list of suppressed diagnostics, so that we don't emit
// them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
// diagnostics again.
Pos->second.clear();
}
// C++ [basic.start.main]p3:
// The function 'main' shall not be used within a program.
if (cast<FunctionDecl>(D)->isMain())
Diag(Loc, diag::ext_main_used);
diagnoseUnavailableAlignedAllocation(*cast<FunctionDecl>(D), Loc);
}
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D)) {
if (isa<BindingDecl>(D)) {
Diag(Loc, diag::err_binding_cannot_appear_in_own_initializer)
<< D->getDeclName();
} else {
Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
<< D->getDeclName() << cast<VarDecl>(D)->getType();
}
return true;
}
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted()) {
auto *Ctor = dyn_cast<CXXConstructorDecl>(FD);
if (Ctor && Ctor->isInheritingConstructor())
Diag(Loc, diag::err_deleted_inherited_ctor_use)
<< Ctor->getParent()
<< Ctor->getInheritedConstructor().getConstructor()->getParent();
else
Diag(Loc, diag::err_deleted_function_use);
NoteDeletedFunction(FD);
return true;
}
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, Loc))
return true;
if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD))
return true;
}
if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
// Lambdas are only default-constructible or assignable in C++2a onwards.
if (MD->getParent()->isLambda() &&
((isa<CXXConstructorDecl>(MD) &&
cast<CXXConstructorDecl>(MD)->isDefaultConstructor()) ||
MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())) {
Diag(Loc, diag::warn_cxx17_compat_lambda_def_ctor_assign)
<< !isa<CXXConstructorDecl>(MD);
}
}
auto getReferencedObjCProp = [](const NamedDecl *D) ->
const ObjCPropertyDecl * {
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->findPropertyDecl();
return nullptr;
};
if (const ObjCPropertyDecl *ObjCPDecl = getReferencedObjCProp(D)) {
if (diagnoseArgIndependentDiagnoseIfAttrs(ObjCPDecl, Loc))
return true;
} else if (diagnoseArgIndependentDiagnoseIfAttrs(D, Loc)) {
return true;
}
// [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
// Only the variables omp_in and omp_out are allowed in the combiner.
// Only the variables omp_priv and omp_orig are allowed in the
// initializer-clause.
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(CurContext);
if (LangOpts.OpenMP && DRD && !CurContext->containsDecl(D) &&
isa<VarDecl>(D)) {
Diag(Loc, diag::err_omp_wrong_var_in_declare_reduction)
<< getCurFunction()->HasOMPDeclareReductionCombiner;
Diag(D->getLocation(), diag::note_entity_declared_at) << D;
return true;
}
// [OpenMP 5.0], 2.19.7.3. declare mapper Directive, Restrictions
// List-items in map clauses on this construct may only refer to the declared
// variable var and entities that could be referenced by a procedure defined
// at the same location
auto *DMD = dyn_cast<OMPDeclareMapperDecl>(CurContext);
if (LangOpts.OpenMP && DMD && !CurContext->containsDecl(D) &&
isa<VarDecl>(D)) {
Diag(Loc, diag::err_omp_declare_mapper_wrong_var)
<< DMD->getVarName().getAsString();
Diag(D->getLocation(), diag::note_entity_declared_at) << D;
return true;
}
DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess,
AvoidPartialAvailabilityChecks, ClassReceiver);
DiagnoseUnusedOfDecl(*this, D, Loc);
diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc);
return false;
}
/// DiagnoseSentinelCalls - This routine checks whether a call or
/// message-send is to a declaration with the sentinel attribute, and
/// if so, it checks that the requirements of the sentinel are
/// satisfied.
void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
ArrayRef<Expr *> Args) {
const SentinelAttr *attr = D->getAttr<SentinelAttr>();
if (!attr)
return;
// The number of formal parameters of the declaration.
unsigned numFormalParams;
// The kind of declaration. This is also an index into a %select in
// the diagnostic.
enum CalleeType { CT_Function, CT_Method, CT_Block } calleeType;
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
numFormalParams = MD->param_size();
calleeType = CT_Method;
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
numFormalParams = FD->param_size();
calleeType = CT_Function;
} else if (isa<VarDecl>(D)) {
QualType type = cast<ValueDecl>(D)->getType();
const FunctionType *fn = nullptr;
if (const PointerType *ptr = type->getAs<PointerType>()) {
fn = ptr->getPointeeType()->getAs<FunctionType>();
if (!fn) return;
calleeType = CT_Function;
} else if (const BlockPointerType *ptr = type->getAs<BlockPointerType>()) {
fn = ptr->getPointeeType()->castAs<FunctionType>();
calleeType = CT_Block;
} else {
return;
}
if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fn)) {
numFormalParams = proto->getNumParams();
} else {
numFormalParams = 0;
}
} else {
return;
}
// "nullPos" is the number of formal parameters at the end which
// effectively count as part of the variadic arguments. This is
// useful if you would prefer to not have *any* formal parameters,
// but the language forces you to have at least one.
unsigned nullPos = attr->getNullPos();
assert((nullPos == 0 || nullPos == 1) && "invalid null position on sentinel");
numFormalParams = (nullPos > numFormalParams ? 0 : numFormalParams - nullPos);
// The number of arguments which should follow the sentinel.
unsigned numArgsAfterSentinel = attr->getSentinel();
// If there aren't enough arguments for all the formal parameters,
// the sentinel, and the args after the sentinel, complain.
if (Args.size() < numFormalParams + numArgsAfterSentinel + 1) {
Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
return;
}
// Otherwise, find the sentinel expression.
Expr *sentinelExpr = Args[Args.size() - numArgsAfterSentinel - 1];
if (!sentinelExpr) return;
if (sentinelExpr->isValueDependent()) return;
if (Context.isSentinelNullExpr(sentinelExpr)) return;
// Pick a reasonable string to insert. Optimistically use 'nil', 'nullptr',
// or 'NULL' if those are actually defined in the context. Only use
// 'nil' for ObjC methods, where it's much more likely that the
// variadic arguments form a list of object pointers.
SourceLocation MissingNilLoc = getLocForEndOfToken(sentinelExpr->getEndLoc());
std::string NullValue;
if (calleeType == CT_Method && PP.isMacroDefined("nil"))
NullValue = "nil";
else if (getLangOpts().CPlusPlus11)
NullValue = "nullptr";
else if (PP.isMacroDefined("NULL"))
NullValue = "NULL";
else
NullValue = "(void*) 0";
if (MissingNilLoc.isInvalid())
Diag(Loc, diag::warn_missing_sentinel) << int(calleeType);
else
Diag(MissingNilLoc, diag::warn_missing_sentinel)
<< int(calleeType)
<< FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue);
Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
}
SourceRange Sema::getExprRange(Expr *E) const {
return E ? E->getSourceRange() : SourceRange();
}
//===----------------------------------------------------------------------===//
// Standard Promotions and Conversions
//===----------------------------------------------------------------------===//
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
E = result.get();
}
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
if (Ty->isFunctionType()) {
if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
if (!checkAddressOfFunctionIsAvailable(FD, Diagnose, E->getExprLoc()))
return ExprError();
E = ImpCastExprToType(E, Context.getPointerType(Ty),
CK_FunctionToPointerDecay).get();
} else if (Ty->isArrayType()) {
// In C90 mode, arrays only promote to pointers if the array expression is
// an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
// type 'array of type' is converted to an expression that has type 'pointer
// to type'...". In C99 this was changed to: C99 6.3.2.1p3: "an expression
// that has type 'array of type' ...". The relevant change is "an lvalue"
// (C90) to "an expression" (C99).
//
// C++ 4.2p1:
// An lvalue or rvalue of type "array of N T" or "array of unknown bound of
// T" can be converted to an rvalue of type "pointer to T".
//
if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue())
E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
CK_ArrayToPointerDecay).get();
}
return E;
}
static void CheckForNullPointerDereference(Sema &S, Expr *E) {
// Check to see if we are dereferencing a null pointer. If so,
// and if not volatile-qualified, this is undefined behavior that the
// optimizer will delete, so warn about it. People sometimes try to use this
// to get a deterministic trap and are surprised by clang's behavior. This
// only handles the pattern "*null", which is a very syntactic check.
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts()))
if (UO->getOpcode() == UO_Deref &&
UO->getSubExpr()->IgnoreParenCasts()->
isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) &&
!UO->getType().isVolatileQualified()) {
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::warn_indirection_through_null)
<< UO->getSubExpr()->getSourceRange());
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::note_indirection_through_null));
}
}
static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
SourceLocation AssignLoc,
const Expr* RHS) {
const ObjCIvarDecl *IV = OIRE->getDecl();
if (!IV)
return;
DeclarationName MemberName = IV->getDeclName();
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
if (!Member || !Member->isStr("isa"))
return;
const Expr *Base = OIRE->getBase();
QualType BaseType = Base->getType();
if (OIRE->isArrow())
BaseType = BaseType->getPointeeType();
if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>())
if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) {
ObjCInterfaceDecl *ClassDeclared = nullptr;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
if (!ClassDeclared->getSuperClass()
&& (*ClassDeclared->ivar_begin()) == IV) {
if (RHS) {
NamedDecl *ObjectSetClass =
S.LookupSingleName(S.TUScope,
&S.Context.Idents.get("object_setClass"),
SourceLocation(), S.LookupOrdinaryName);
if (ObjectSetClass) {
SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getEndLoc());
S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign)
<< FixItHint::CreateInsertion(OIRE->getBeginLoc(),
"object_setClass(")
<< FixItHint::CreateReplacement(
SourceRange(OIRE->getOpLoc(), AssignLoc), ",")
<< FixItHint::CreateInsertion(RHSLocEnd, ")");
}
else
S.Diag(OIRE->getLocation(), diag::warn_objc_isa_assign);
} else {
NamedDecl *ObjectGetClass =
S.LookupSingleName(S.TUScope,
&S.Context.Idents.get("object_getClass"),
SourceLocation(), S.LookupOrdinaryName);
if (ObjectGetClass)
S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use)
<< FixItHint::CreateInsertion(OIRE->getBeginLoc(),
"object_getClass(")
<< FixItHint::CreateReplacement(
SourceRange(OIRE->getOpLoc(), OIRE->getEndLoc()), ")");
else
S.Diag(OIRE->getLocation(), diag::warn_objc_isa_use);
}
S.Diag(IV->getLocation(), diag::note_ivar_decl);
}
}
}
ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
E = result.get();
}
// C++ [conv.lval]p1:
// A glvalue of a non-function, non-array type T can be
// converted to a prvalue.
if (!E->isGLValue()) return E;
QualType T = E->getType();
assert(!T.isNull() && "r-value conversion on typeless expression?");
// We don't want to throw lvalue-to-rvalue casts on top of
// expressions of certain types in C++.
if (getLangOpts().CPlusPlus &&
(E->getType() == Context.OverloadTy ||
T->isDependentType() ||
T->isRecordType()))
return E;
// The C standard is actually really unclear on this point, and
// DR106 tells us what the result should be but not why. It's
// generally best to say that void types just doesn't undergo
// lvalue-to-rvalue at all. Note that expressions of unqualified
// 'void' type are never l-values, but qualified void can be.
if (T->isVoidType())
return E;
// OpenCL usually rejects direct accesses to values of 'half' type.
if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
T->isHalfType()) {
Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
<< 0 << T;
return ExprError();
}
CheckForNullPointerDereference(*this, E);
if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(E->IgnoreParenCasts())) {
NamedDecl *ObjectGetClass = LookupSingleName(TUScope,
&Context.Idents.get("object_getClass"),
SourceLocation(), LookupOrdinaryName);
if (ObjectGetClass)
Diag(E->getExprLoc(), diag::warn_objc_isa_use)
<< FixItHint::CreateInsertion(OISA->getBeginLoc(), "object_getClass(")
<< FixItHint::CreateReplacement(
SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")");
else
Diag(E->getExprLoc(), diag::warn_objc_isa_use);
}
else if (const ObjCIvarRefExpr *OIRE =
dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/nullptr);
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
// cv-unqualified version of T. Otherwise, the type of the
// rvalue is T.
//
// C99 6.3.2.1p2:
// If the lvalue has qualified type, the value has the unqualified
// version of the type of the lvalue; otherwise, the value has the
// type of the lvalue.
if (T.hasQualifiers())
T = T.getUnqualifiedType();
// Under the MS ABI, lock down the inheritance model now.
if (T->isMemberPointerType() &&
Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(E->getExprLoc(), T);
ExprResult Res = CheckLValueToRValueConversionOperand(E);
if (Res.isInvalid())
return Res;
E = Res.get();
// Loading a __weak object implicitly retains the value, so we need a cleanup to
// balance that.
if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
Cleanup.setExprNeedsCleanups(true);
// C++ [conv.lval]p3:
// If T is cv std::nullptr_t, the result is a null pointer constant.
CastKind CK = T->isNullPtrType() ? CK_NullToPointer : CK_LValueToRValue;
Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue);
// C11 6.3.2.1p2:
// ... if the lvalue has atomic type, the value has the non-atomic version
// of the type of the lvalue ...
if (const AtomicType *Atomic = T->getAs<AtomicType>()) {
T = Atomic->getValueType().getUnqualifiedType();
Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(),
nullptr, VK_RValue);
}
return Res;
}
ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose) {
ExprResult Res = DefaultFunctionArrayConversion(E, Diagnose);
if (Res.isInvalid())
return ExprError();
Res = DefaultLvalueConversion(Res.get());
if (Res.isInvalid())
return ExprError();
return Res;
}
/// CallExprUnaryConversions - a special case of an unary conversion
/// performed on a function designator of a call expression.
ExprResult Sema::CallExprUnaryConversions(Expr *E) {
QualType Ty = E->getType();
ExprResult Res = E;
// Only do implicit cast for a function type, but not for a pointer
// to function type.
if (Ty->isFunctionType()) {
Res = ImpCastExprToType(E, Context.getPointerType(Ty),
CK_FunctionToPointerDecay).get();
if (Res.isInvalid())
return ExprError();
}
Res = DefaultLvalueConversion(Res.get());
if (Res.isInvalid())
return ExprError();
return Res.get();
}
/// UsualUnaryConversions - Performs various conversions that are common to most
/// operators (C99 6.3). The conversions of array and function types are
/// sometimes suppressed. For example, the array->pointer conversion doesn't
/// apply if the array is an argument to the sizeof or address (&) operators.
/// In these instances, this routine should *not* be called.
ExprResult Sema::UsualUnaryConversions(Expr *E) {
// First, convert to an r-value.
ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
if (Res.isInvalid())
return ExprError();
E = Res.get();
QualType Ty = E->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
// Half FP have to be promoted to float unless it is natively supported
if (Ty->isHalfType() && !getLangOpts().NativeHalfType)
return ImpCastExprToType(Res.get(), Context.FloatTy, CK_FloatingCast);
// Try to perform integral promotions if the object has a theoretically
// promotable type.
if (Ty->isIntegralOrUnscopedEnumerationType()) {
// C99 6.3.1.1p2:
//
// The following may be used in an expression wherever an int or
// unsigned int may be used:
// - an object or expression with an integer type whose integer
// conversion rank is less than or equal to the rank of int
// and unsigned int.
// - A bit-field of type _Bool, int, signed int, or unsigned int.
//
// If an int can represent all values of the original type, the
// value is converted to an int; otherwise, it is converted to an
// unsigned int. These are called the integer promotions. All
// other types are unchanged by the integer promotions.
QualType PTy = Context.isPromotableBitField(E);
if (!PTy.isNull()) {
E = ImpCastExprToType(E, PTy, CK_IntegralCast).get();
return E;
}
if (Ty->isPromotableIntegerType()) {
QualType PT = Context.getPromotedIntegerType(Ty);
E = ImpCastExprToType(E, PT, CK_IntegralCast).get();
return E;
}
}
return E;
}
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
/// do not have a prototype. Arguments that have type float or __fp16
/// are promoted to double. All other argument types are converted by
/// UsualUnaryConversions().
ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
ExprResult Res = UsualUnaryConversions(E);
if (Res.isInvalid())
return ExprError();
E = Res.get();
// If this is a 'float' or '__fp16' (CVR qualified or typedef)
// promote to double.
// Note that default argument promotion applies only to float (and
// half/fp16); it does not apply to _Float16.
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (BTy && (BTy->getKind() == BuiltinType::Half ||
BTy->getKind() == BuiltinType::Float)) {
if (getLangOpts().OpenCL &&
!getOpenCLOptions().isEnabled("cl_khr_fp64")) {
if (BTy->getKind() == BuiltinType::Half) {
E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
}
} else {
E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
}
}
// C++ performs lvalue-to-rvalue conversion as a default argument
// promotion, even on class types, but note:
// C++11 [conv.lval]p2:
// When an lvalue-to-rvalue conversion occurs in an unevaluated
// operand or a subexpression thereof the value contained in the
// referenced object is not accessed. Otherwise, if the glvalue
// has a class type, the conversion copy-initializes a temporary
// of type T from the glvalue and the result of the conversion
// is a prvalue for the temporary.
// FIXME: add some way to gate this entire thing for correctness in
// potentially potentially evaluated contexts.
if (getLangOpts().CPlusPlus && E->isGLValue() && !isUnevaluatedContext()) {
ExprResult Temp = PerformCopyInitialization(
InitializedEntity::InitializeTemporary(E->getType()),
E->getExprLoc(), E);
if (Temp.isInvalid())
return ExprError();
E = Temp.get();
}
return E;
}
/// Determine the degree of POD-ness for an expression.
/// Incomplete types are considered POD, since this check can be performed
/// when we're in an unevaluated context.
Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
if (Ty->isIncompleteType()) {
// C++11 [expr.call]p7:
// After these conversions, if the argument does not have arithmetic,
// enumeration, pointer, pointer to member, or class type, the program
// is ill-formed.
//
// Since we've already performed array-to-pointer and function-to-pointer
// decay, the only such type in C++ is cv void. This also handles
// initializer lists as variadic arguments.
if (Ty->isVoidType())
return VAK_Invalid;
if (Ty->isObjCObjectType())
return VAK_Invalid;
return VAK_Valid;
}
if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
return VAK_Invalid;
if (Ty.isCXX98PODType(Context))
return VAK_Valid;
// C++11 [expr.call]p7:
// Passing a potentially-evaluated argument of class type (Clause 9)
// having a non-trivial copy constructor, a non-trivial move constructor,
// or a non-trivial destructor, with no corresponding parameter,
// is conditionally-supported with implementation-defined semantics.
if (getLangOpts().CPlusPlus11 && !Ty->isDependentType())
if (CXXRecordDecl *Record = Ty->getAsCXXRecordDecl())
if (!Record->hasNonTrivialCopyConstructor() &&
!Record->hasNonTrivialMoveConstructor() &&
!Record->hasNonTrivialDestructor())
return VAK_ValidInCXX11;
if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType())
return VAK_Valid;
if (Ty->isObjCObjectType())
return VAK_Invalid;
if (getLangOpts().MSVCCompat)
return VAK_MSVCUndefined;
// FIXME: In C++11, these cases are conditionally-supported, meaning we're
// permitted to reject them. We should consider doing so.
return VAK_Undefined;
}
void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
// Don't allow one to pass an Objective-C interface to a vararg.
const QualType &Ty = E->getType();
VarArgKind VAK = isValidVarArgType(Ty);
// Complain about passing non-POD types through varargs.
switch (VAK) {
case VAK_ValidInCXX11:
DiagRuntimeBehavior(
E->getBeginLoc(), nullptr,
PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg) << Ty << CT);
LLVM_FALLTHROUGH;
case VAK_Valid:
if (Ty->isRecordType()) {
// This is unlikely to be what the user intended. If the class has a
// 'c_str' member function, the user probably meant to call that.
DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
PDiag(diag::warn_pass_class_arg_to_vararg)
<< Ty << CT << hasCStrMethod(E) << ".c_str()");
}
break;
case VAK_Undefined:
case VAK_MSVCUndefined:
DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< getLangOpts().CPlusPlus11 << Ty << CT);
break;
case VAK_Invalid:
if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
Diag(E->getBeginLoc(),
diag::err_cannot_pass_non_trivial_c_struct_to_vararg)
<< Ty << CT;
else if (Ty->isObjCObjectType())
DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
<< Ty << CT);
else
Diag(E->getBeginLoc(), diag::err_cannot_pass_to_vararg)
<< isa<InitListExpr>(E) << Ty << CT;
break;
}
}
/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
/// will create a trap if the resulting type is not a POD type.
ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
FunctionDecl *FDecl) {
if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) {
// Strip the unbridged-cast placeholder expression off, if applicable.
if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast &&
(CT == VariadicMethod ||
(FDecl && FDecl->hasAttr<CFAuditedTransferAttr>()))) {
E = stripARCUnbridgedCast(E);
// Otherwise, do normal placeholder checking.
} else {
ExprResult ExprRes = CheckPlaceholderExpr(E);
if (ExprRes.isInvalid())
return ExprError();
E = ExprRes.get();
}
}
ExprResult ExprRes = DefaultArgumentPromotion(E);
if (ExprRes.isInvalid())
return ExprError();
E = ExprRes.get();
// Diagnostics regarding non-POD argument types are
// emitted along with format string checking in Sema::CheckFunctionCall().
if (isValidVarArgType(E->getType()) == VAK_Undefined) {
// Turn this into a trap.
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
E->getBeginLoc());
ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, Name,
/*HasTrailingLParen=*/true,
/*IsAddressOfOperand=*/false);
if (TrapFn.isInvalid())
return ExprError();
ExprResult Call = BuildCallExpr(TUScope, TrapFn.get(), E->getBeginLoc(),
None, E->getEndLoc());
if (Call.isInvalid())
return ExprError();
ExprResult Comma =
ActOnBinOp(TUScope, E->getBeginLoc(), tok::comma, Call.get(), E);
if (Comma.isInvalid())
return ExprError();
return Comma.get();
}
if (!getLangOpts().CPlusPlus &&
RequireCompleteType(E->getExprLoc(), E->getType(),
diag::err_call_incomplete_argument))
return ExprError();
return E;
}
/// Converts an integer to complex float type. Helper function of
/// UsualArithmeticConversions()
///
/// \return false if the integer expression is an integer type and is
/// successfully converted to the complex type.
static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr,
ExprResult &ComplexExpr,
QualType IntTy,
QualType ComplexTy,
bool SkipCast) {
if (IntTy->isComplexType() || IntTy->isRealFloatingType()) return true;
if (SkipCast) return false;
if (IntTy->isIntegerType()) {
QualType fpTy = cast<ComplexType>(ComplexTy)->getElementType();
IntExpr = S.ImpCastExprToType(IntExpr.get(), fpTy, CK_IntegralToFloating);
IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy,
CK_FloatingRealToComplex);
} else {
assert(IntTy->isComplexIntegerType());
IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy,
CK_IntegralComplexToFloatingComplex);
}
return false;
}
/// Handle arithmetic conversion with complex types. Helper function of
/// UsualArithmeticConversions()
static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType,
bool IsCompAssign) {
// if we have an integer operand, the result is the complex type.
if (!handleIntegerToComplexFloatConversion(S, RHS, LHS, RHSType, LHSType,
/*skipCast*/false))
return LHSType;
if (!handleIntegerToComplexFloatConversion(S, LHS, RHS, LHSType, RHSType,
/*skipCast*/IsCompAssign))
return RHSType;
// This handles complex/complex, complex/float, or float/complex.
// When both operands are complex, the shorter operand is converted to the
// type of the longer, and that is the type of the result. This corresponds
// to what is done when combining two real floating-point operands.
// The fun begins when size promotion occur across type domains.
// From H&S 6.3.4: When one operand is complex and the other is a real
// floating-point type, the less precise type is converted, within it's
// real or complex domain, to the precision of the other type. For example,
// when combining a "long double" with a "double _Complex", the
// "double _Complex" is promoted to "long double _Complex".
// Compute the rank of the two types, regardless of whether they are complex.
int Order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
auto *LHSComplexType = dyn_cast<ComplexType>(LHSType);
auto *RHSComplexType = dyn_cast<ComplexType>(RHSType);
QualType LHSElementType =
LHSComplexType ? LHSComplexType->getElementType() : LHSType;
QualType RHSElementType =
RHSComplexType ? RHSComplexType->getElementType() : RHSType;
QualType ResultType = S.Context.getComplexType(LHSElementType);
if (Order < 0) {
// Promote the precision of the LHS if not an assignment.
ResultType = S.Context.getComplexType(RHSElementType);
if (!IsCompAssign) {
if (LHSComplexType)
LHS =
S.ImpCastExprToType(LHS.get(), ResultType, CK_FloatingComplexCast);
else
LHS = S.ImpCastExprToType(LHS.get(), RHSElementType, CK_FloatingCast);
}
} else if (Order > 0) {
// Promote the precision of the RHS.
if (RHSComplexType)
RHS = S.ImpCastExprToType(RHS.get(), ResultType, CK_FloatingComplexCast);
else
RHS = S.ImpCastExprToType(RHS.get(), LHSElementType, CK_FloatingCast);
}
return ResultType;
}
/// Handle arithmetic conversion from integer to float. Helper function
/// of UsualArithmeticConversions()
static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
ExprResult &IntExpr,
QualType FloatTy, QualType IntTy,
bool ConvertFloat, bool ConvertInt) {
if (IntTy->isIntegerType()) {
if (ConvertInt)
// Convert intExpr to the lhs floating point type.
IntExpr = S.ImpCastExprToType(IntExpr.get(), FloatTy,
CK_IntegralToFloating);
return FloatTy;
}
// Convert both sides to the appropriate complex float.
assert(IntTy->isComplexIntegerType());
QualType result = S.Context.getComplexType(FloatTy);
// _Complex int -> _Complex float
if (ConvertInt)
IntExpr = S.ImpCastExprToType(IntExpr.get(), result,
CK_IntegralComplexToFloatingComplex);
// float -> _Complex float
if (ConvertFloat)
FloatExpr = S.ImpCastExprToType(FloatExpr.get(), result,
CK_FloatingRealToComplex);
return result;
}
/// Handle arithmethic conversion with floating point types. Helper
/// function of UsualArithmeticConversions()
static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType, bool IsCompAssign) {
bool LHSFloat = LHSType->isRealFloatingType();
bool RHSFloat = RHSType->isRealFloatingType();
// If we have two real floating types, convert the smaller operand
// to the bigger result.
if (LHSFloat && RHSFloat) {
int order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
if (order > 0) {
RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FloatingCast);
return LHSType;
}
assert(order < 0 && "illegal float comparison");
if (!IsCompAssign)
LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FloatingCast);
return RHSType;
}
if (LHSFloat) {
// Half FP has to be promoted to float unless it is natively supported
if (LHSType->isHalfType() && !S.getLangOpts().NativeHalfType)
LHSType = S.Context.FloatTy;
return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType,
/*ConvertFloat=*/!IsCompAssign,
/*ConvertInt=*/ true);
}
assert(RHSFloat);
return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
/*convertInt=*/ true,
/*convertFloat=*/!IsCompAssign);
}
/// Diagnose attempts to convert between __float128 and long double if
/// there is no support for such conversion. Helper function of
/// UsualArithmeticConversions().
static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
QualType RHSType) {
/* No issue converting if at least one of the types is not a floating point
type or the two types have the same rank.
*/
if (!LHSType->isFloatingType() || !RHSType->isFloatingType() ||
S.Context.getFloatingTypeOrder(LHSType, RHSType) == 0)
return false;
assert(LHSType->isFloatingType() && RHSType->isFloatingType() &&
"The remaining types must be floating point types.");
auto *LHSComplex = LHSType->getAs<ComplexType>();
auto *RHSComplex = RHSType->getAs<ComplexType>();
QualType LHSElemType = LHSComplex ?
LHSComplex->getElementType() : LHSType;
QualType RHSElemType = RHSComplex ?
RHSComplex->getElementType() : RHSType;
// No issue if the two types have the same representation
if (&S.Context.getFloatTypeSemantics(LHSElemType) ==
&S.Context.getFloatTypeSemantics(RHSElemType))
return false;
bool Float128AndLongDouble = (LHSElemType == S.Context.Float128Ty &&
RHSElemType == S.Context.LongDoubleTy);
Float128AndLongDouble |= (LHSElemType == S.Context.LongDoubleTy &&
RHSElemType == S.Context.Float128Ty);
// We've handled the situation where __float128 and long double have the same
// representation. We allow all conversions for all possible long double types
// except PPC's double double.
return Float128AndLongDouble &&
(&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
&llvm::APFloat::PPCDoubleDouble());
}
typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType);
namespace {
/// These helper callbacks are placed in an anonymous namespace to
/// permit their use as function template parameters.
ExprResult doIntegralCast(Sema &S, Expr *op, QualType toType) {
return S.ImpCastExprToType(op, toType, CK_IntegralCast);
}
ExprResult doComplexIntegralCast(Sema &S, Expr *op, QualType toType) {
return S.ImpCastExprToType(op, S.Context.getComplexType(toType),
CK_IntegralComplexCast);
}
}
/// Handle integer arithmetic conversions. Helper function of
/// UsualArithmeticConversions()
template <PerformCastFn doLHSCast, PerformCastFn doRHSCast>
static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType, bool IsCompAssign) {
// The rules for this case are in C99 6.3.1.8
int order = S.Context.getIntegerTypeOrder(LHSType, RHSType);
bool LHSSigned = LHSType->hasSignedIntegerRepresentation();
bool RHSSigned = RHSType->hasSignedIntegerRepresentation();
if (LHSSigned == RHSSigned) {
// Same signedness; use the higher-ranked type
if (order >= 0) {
RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else if (order != (LHSSigned ? 1 : -1)) {
// The unsigned type has greater than or equal rank to the
// signed type, so use the unsigned type
if (RHSSigned) {
RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else if (S.Context.getIntWidth(LHSType) != S.Context.getIntWidth(RHSType)) {
// The two types are different widths; if we are here, that
// means the signed type is larger than the unsigned type, so
// use the signed type.
if (LHSSigned) {
RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else {
// The signed type is higher-ranked than the unsigned type,
// but isn't actually any bigger (like unsigned int and long
// on most 32-bit systems). Use the unsigned type corresponding
// to the signed type.
QualType result =
S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType);
RHS = (*doRHSCast)(S, RHS.get(), result);
if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), result);
return result;
}
}
/// Handle conversions with GCC complex int extension. Helper function
/// of UsualArithmeticConversions()
static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType,
bool IsCompAssign) {
const ComplexType *LHSComplexInt = LHSType->getAsComplexIntegerType();
const ComplexType *RHSComplexInt = RHSType->getAsComplexIntegerType();
if (LHSComplexInt && RHSComplexInt) {
QualType LHSEltType = LHSComplexInt->getElementType();
QualType RHSEltType = RHSComplexInt->getElementType();
QualType ScalarType =
handleIntegerConversion<doComplexIntegralCast, doComplexIntegralCast>
(S, LHS, RHS, LHSEltType, RHSEltType, IsCompAssign);
return S.Context.getComplexType(ScalarType);
}
if (LHSComplexInt) {
QualType LHSEltType = LHSComplexInt->getElementType();
QualType ScalarType =
handleIntegerConversion<doComplexIntegralCast, doIntegralCast>
(S, LHS, RHS, LHSEltType, RHSType, IsCompAssign);
QualType ComplexType = S.Context.getComplexType(ScalarType);
RHS = S.ImpCastExprToType(RHS.get(), ComplexType,
CK_IntegralRealToComplex);
return ComplexType;
}
assert(RHSComplexInt);
QualType RHSEltType = RHSComplexInt->getElementType();
QualType ScalarType =
handleIntegerConversion<doIntegralCast, doComplexIntegralCast>
(S, LHS, RHS, LHSType, RHSEltType, IsCompAssign);
QualType ComplexType = S.Context.getComplexType(ScalarType);
if (!IsCompAssign)
LHS = S.ImpCastExprToType(LHS.get(), ComplexType,
CK_IntegralRealToComplex);
return ComplexType;
}
/// Return the rank of a given fixed point or integer type. The value itself
/// doesn't matter, but the values must be increasing with proper increasing
/// rank as described in N1169 4.1.1.
static unsigned GetFixedPointRank(QualType Ty) {
const auto *BTy = Ty->getAs<BuiltinType>();
assert(BTy && "Expected a builtin type.");
switch (BTy->getKind()) {
case BuiltinType::ShortFract:
case BuiltinType::UShortFract:
case BuiltinType::SatShortFract:
case BuiltinType::SatUShortFract:
return 1;
case BuiltinType::Fract:
case BuiltinType::UFract:
case BuiltinType::SatFract:
case BuiltinType::SatUFract:
return 2;
case BuiltinType::LongFract:
case BuiltinType::ULongFract:
case BuiltinType::SatLongFract:
case BuiltinType::SatULongFract:
return 3;
case BuiltinType::ShortAccum:
case BuiltinType::UShortAccum:
case BuiltinType::SatShortAccum:
case BuiltinType::SatUShortAccum:
return 4;
case BuiltinType::Accum:
case BuiltinType::UAccum:
case BuiltinType::SatAccum:
case BuiltinType::SatUAccum:
return 5;
case BuiltinType::LongAccum:
case BuiltinType::ULongAccum:
case BuiltinType::SatLongAccum:
case BuiltinType::SatULongAccum:
return 6;
default:
if (BTy->isInteger())
return 0;
llvm_unreachable("Unexpected fixed point or integer type");
}
}
/// handleFixedPointConversion - Fixed point operations between fixed
/// point types and integers or other fixed point types do not fall under
/// usual arithmetic conversion since these conversions could result in loss
/// of precsision (N1169 4.1.4). These operations should be calculated with
/// the full precision of their result type (N1169 4.1.6.2.1).
static QualType handleFixedPointConversion(Sema &S, QualType LHSTy,
QualType RHSTy) {
assert((LHSTy->isFixedPointType() || RHSTy->isFixedPointType()) &&
"Expected at least one of the operands to be a fixed point type");
assert((LHSTy->isFixedPointOrIntegerType() ||
RHSTy->isFixedPointOrIntegerType()) &&
"Special fixed point arithmetic operation conversions are only "
"applied to ints or other fixed point types");
// If one operand has signed fixed-point type and the other operand has
// unsigned fixed-point type, then the unsigned fixed-point operand is
// converted to its corresponding signed fixed-point type and the resulting
// type is the type of the converted operand.
if (RHSTy->isSignedFixedPointType() && LHSTy->isUnsignedFixedPointType())
LHSTy = S.Context.getCorrespondingSignedFixedPointType(LHSTy);
else if (RHSTy->isUnsignedFixedPointType() && LHSTy->isSignedFixedPointType())
RHSTy = S.Context.getCorrespondingSignedFixedPointType(RHSTy);
// The result type is the type with the highest rank, whereby a fixed-point
// conversion rank is always greater than an integer conversion rank; if the
// type of either of the operands is a saturating fixedpoint type, the result
// type shall be the saturating fixed-point type corresponding to the type
// with the highest rank; the resulting value is converted (taking into
// account rounding and overflow) to the precision of the resulting type.
// Same ranks between signed and unsigned types are resolved earlier, so both
// types are either signed or both unsigned at this point.
unsigned LHSTyRank = GetFixedPointRank(LHSTy);
unsigned RHSTyRank = GetFixedPointRank(RHSTy);
QualType ResultTy = LHSTyRank > RHSTyRank ? LHSTy : RHSTy;
if (LHSTy->isSaturatedFixedPointType() || RHSTy->isSaturatedFixedPointType())
ResultTy = S.Context.getCorrespondingSaturatedType(ResultTy);
return ResultTy;
}
/// UsualArithmeticConversions - Performs various conversions that are common to
/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
/// routine returns the first non-arithmetic type found. The client is
/// responsible for emitting appropriate error diagnostics.
QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
bool IsCompAssign) {
if (!IsCompAssign) {
LHS = UsualUnaryConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
}
RHS = UsualUnaryConversions(RHS.get());
if (RHS.isInvalid())
return QualType();
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
QualType LHSType =
Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
QualType RHSType =
Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
// For conversion purposes, we ignore any atomic qualifier on the LHS.
if (const AtomicType *AtomicLHS = LHSType->getAs<AtomicType>())
LHSType = AtomicLHS->getValueType();
// If both types are identical, no conversion is needed.
if (LHSType == RHSType)
return LHSType;
// If either side is a non-arithmetic type (e.g. a pointer), we are done.
// The caller can deal with this (e.g. pointer + int).
if (!LHSType->isArithmeticType() || !RHSType->isArithmeticType())
return QualType();
// Apply unary and bitfield promotions to the LHS's type.
QualType LHSUnpromotedType = LHSType;
if (LHSType->isPromotableIntegerType())
LHSType = Context.getPromotedIntegerType(LHSType);
QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(LHS.get());
if (!LHSBitfieldPromoteTy.isNull())
LHSType = LHSBitfieldPromoteTy;
if (LHSType != LHSUnpromotedType && !IsCompAssign)
LHS = ImpCastExprToType(LHS.get(), LHSType, CK_IntegralCast);
// If both types are identical, no conversion is needed.
if (LHSType == RHSType)
return LHSType;
// At this point, we have two different arithmetic types.
// Diagnose attempts to convert between __float128 and long double where
// such conversions currently can't be handled.
if (unsupportedTypeConversion(*this, LHSType, RHSType))
return QualType();
// Handle complex types first (C99 6.3.1.8p1).
if (LHSType->isComplexType() || RHSType->isComplexType())
return handleComplexFloatConversion(*this, LHS, RHS, LHSType, RHSType,
IsCompAssign);
// Now handle "real" floating types (i.e. float, double, long double).
if (LHSType->isRealFloatingType() || RHSType->isRealFloatingType())
return handleFloatConversion(*this, LHS, RHS, LHSType, RHSType,
IsCompAssign);
// Handle GCC complex int extension.
if (LHSType->isComplexIntegerType() || RHSType->isComplexIntegerType())
return handleComplexIntConversion(*this, LHS, RHS, LHSType, RHSType,
IsCompAssign);
if (LHSType->isFixedPointType() || RHSType->isFixedPointType())
return handleFixedPointConversion(*this, LHSType, RHSType);
// Finally, we have two differing integer types.
return handleIntegerConversion<doIntegralCast, doIntegralCast>
(*this, LHS, RHS, LHSType, RHSType, IsCompAssign);
}
//===----------------------------------------------------------------------===//
// Semantic Analysis for various Expression Types
//===----------------------------------------------------------------------===//
ExprResult
Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
ArrayRef<ParsedType> ArgTypes,
ArrayRef<Expr *> ArgExprs) {
unsigned NumAssocs = ArgTypes.size();
assert(NumAssocs == ArgExprs.size());
TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs];
for (unsigned i = 0; i < NumAssocs; ++i) {
if (ArgTypes[i])
(void) GetTypeFromParser(ArgTypes[i], &Types[i]);
else
Types[i] = nullptr;
}
ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
ControllingExpr,
llvm::makeArrayRef(Types, NumAssocs),
ArgExprs);
delete [] Types;
return ER;
}
ExprResult
Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
ArrayRef<TypeSourceInfo *> Types,
ArrayRef<Expr *> Exprs) {
unsigned NumAssocs = Types.size();
assert(NumAssocs == Exprs.size());
// Decay and strip qualifiers for the controlling expression type, and handle
// placeholder type replacement. See committee discussion from WG14 DR423.
{
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
ExprResult R = DefaultFunctionArrayLvalueConversion(ControllingExpr);
if (R.isInvalid())
return ExprError();
ControllingExpr = R.get();
}
// The controlling expression is an unevaluated operand, so side effects are
// likely unintended.
if (!inTemplateInstantiation() &&
ControllingExpr->HasSideEffects(Context, false))
Diag(ControllingExpr->getExprLoc(),
diag::warn_side_effects_unevaluated_context);
bool TypeErrorFound = false,
IsResultDependent = ControllingExpr->isTypeDependent(),
ContainsUnexpandedParameterPack
= ControllingExpr->containsUnexpandedParameterPack();
for (unsigned i = 0; i < NumAssocs; ++i) {
if (Exprs[i]->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
if (Types[i]) {
if (Types[i]->getType()->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
if (Types[i]->getType()->isDependentType()) {
IsResultDependent = true;
} else {
// C11 6.5.1.1p2 "The type name in a generic association shall specify a
// complete object type other than a variably modified type."
unsigned D = 0;
if (Types[i]->getType()->isIncompleteType())
D = diag::err_assoc_type_incomplete;
else if (!Types[i]->getType()->isObjectType())
D = diag::err_assoc_type_nonobject;
else if (Types[i]->getType()->isVariablyModifiedType())
D = diag::err_assoc_type_variably_modified;
if (D != 0) {
Diag(Types[i]->getTypeLoc().getBeginLoc(), D)
<< Types[i]->getTypeLoc().getSourceRange()
<< Types[i]->getType();
TypeErrorFound = true;
}
// C11 6.5.1.1p2 "No two generic associations in the same generic
// selection shall specify compatible types."
for (unsigned j = i+1; j < NumAssocs; ++j)
if (Types[j] && !Types[j]->getType()->isDependentType() &&
Context.typesAreCompatible(Types[i]->getType(),
Types[j]->getType())) {
Diag(Types[j]->getTypeLoc().getBeginLoc(),
diag::err_assoc_compatible_types)
<< Types[j]->getTypeLoc().getSourceRange()
<< Types[j]->getType()
<< Types[i]->getType();
Diag(Types[i]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
<< Types[i]->getTypeLoc().getSourceRange()
<< Types[i]->getType();
TypeErrorFound = true;
}
}
}
}
if (TypeErrorFound)
return ExprError();
// If we determined that the generic selection is result-dependent, don't
// try to compute the result expression.
if (IsResultDependent)
return GenericSelectionExpr::Create(Context, KeyLoc, ControllingExpr, Types,
Exprs, DefaultLoc, RParenLoc,
ContainsUnexpandedParameterPack);
SmallVector<unsigned, 1> CompatIndices;
unsigned DefaultIndex = -1U;
for (unsigned i = 0; i < NumAssocs; ++i) {
if (!Types[i])
DefaultIndex = i;
else if (Context.typesAreCompatible(ControllingExpr->getType(),
Types[i]->getType()))
CompatIndices.push_back(i);
}
// C11 6.5.1.1p2 "The controlling expression of a generic selection shall have
// type compatible with at most one of the types named in its generic
// association list."
if (CompatIndices.size() > 1) {
// We strip parens here because the controlling expression is typically
// parenthesized in macro definitions.
ControllingExpr = ControllingExpr->IgnoreParens();
Diag(ControllingExpr->getBeginLoc(), diag::err_generic_sel_multi_match)
<< ControllingExpr->getSourceRange() << ControllingExpr->getType()
<< (unsigned)CompatIndices.size();
for (unsigned I : CompatIndices) {
Diag(Types[I]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
<< Types[I]->getTypeLoc().getSourceRange()
<< Types[I]->getType();
}
return ExprError();
}
// C11 6.5.1.1p2 "If a generic selection has no default generic association,
// its controlling expression shall have type compatible with exactly one of
// the types named in its generic association list."
if (DefaultIndex == -1U && CompatIndices.size() == 0) {
// We strip parens here because the controlling expression is typically
// parenthesized in macro definitions.
ControllingExpr = ControllingExpr->IgnoreParens();
Diag(ControllingExpr->getBeginLoc(), diag::err_generic_sel_no_match)
<< ControllingExpr->getSourceRange() << ControllingExpr->getType();
return ExprError();
}
// C11 6.5.1.1p3 "If a generic selection has a generic association with a
// type name that is compatible with the type of the controlling expression,
// then the result expression of the generic selection is the expression
// in that generic association. Otherwise, the result expression of the
// generic selection is the expression in the default generic association."
unsigned ResultIndex =
CompatIndices.size() ? CompatIndices[0] : DefaultIndex;
return GenericSelectionExpr::Create(
Context, KeyLoc, ControllingExpr, Types, Exprs, DefaultLoc, RParenLoc,
ContainsUnexpandedParameterPack, ResultIndex);
}
/// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the
/// location of the token and the offset of the ud-suffix within it.
static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc,
unsigned Offset) {
return Lexer::AdvanceToTokenCharacter(TokLoc, Offset, S.getSourceManager(),
S.getLangOpts());
}
/// BuildCookedLiteralOperatorCall - A user-defined literal was found. Look up
/// the corresponding cooked (non-raw) literal operator, and build a call to it.
static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
IdentifierInfo *UDSuffix,
SourceLocation UDSuffixLoc,
ArrayRef<Expr*> Args,
SourceLocation LitEndLoc) {
assert(Args.size() <= 2 && "too many arguments for literal operator");
QualType ArgTy[2];
for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
ArgTy[ArgIdx] = Args[ArgIdx]->getType();
if (ArgTy[ArgIdx]->isArrayType())
ArgTy[ArgIdx] = S.Context.getArrayDecayedType(ArgTy[ArgIdx]);
}
DeclarationName OpName =
S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
/*AllowRaw*/ false, /*AllowTemplate*/ false,
/*AllowStringTemplate*/ false,
/*DiagnoseMissing*/ true) == Sema::LOLR_Error)
return ExprError();
return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);
}
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
/// multiple tokens. However, the common case is that StringToks points to one
/// string.
///
ExprResult
Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
assert(!StringToks.empty() && "Must have at least one string!");
StringLiteralParser Literal(StringToks, PP);
if (Literal.hadError)
return ExprError();
SmallVector<SourceLocation, 4> StringTokLocs;
for (const Token &Tok : StringToks)
StringTokLocs.push_back(Tok.getLocation());
QualType CharTy = Context.CharTy;
StringLiteral::StringKind Kind = StringLiteral::Ascii;
if (Literal.isWide()) {
CharTy = Context.getWideCharType();
Kind = StringLiteral::Wide;
} else if (Literal.isUTF8()) {
if (getLangOpts().Char8)
CharTy = Context.Char8Ty;
Kind = StringLiteral::UTF8;
} else if (Literal.isUTF16()) {
CharTy = Context.Char16Ty;
Kind = StringLiteral::UTF16;
} else if (Literal.isUTF32()) {
CharTy = Context.Char32Ty;
Kind = StringLiteral::UTF32;
} else if (Literal.isPascal()) {
CharTy = Context.UnsignedCharTy;
}
// Warn on initializing an array of char from a u8 string literal; this
// becomes ill-formed in C++2a.
if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus2a &&
!getLangOpts().Char8 && Kind == StringLiteral::UTF8) {
Diag(StringTokLocs.front(), diag::warn_cxx2a_compat_utf8_string);
// Create removals for all 'u8' prefixes in the string literal(s). This
// ensures C++2a compatibility (but may change the program behavior when
// built by non-Clang compilers for which the execution character set is
// not always UTF-8).
auto RemovalDiag = PDiag(diag::note_cxx2a_compat_utf8_string_remove_u8);
SourceLocation RemovalDiagLoc;
for (const Token &Tok : StringToks) {
if (Tok.getKind() == tok::utf8_string_literal) {
if (RemovalDiagLoc.isInvalid())
RemovalDiagLoc = Tok.getLocation();
RemovalDiag << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
Tok.getLocation(),
Lexer::AdvanceToTokenCharacter(Tok.getLocation(), 2,
getSourceManager(), getLangOpts())));
}
}
Diag(RemovalDiagLoc, RemovalDiag);
}
QualType StrTy =
Context.getStringLiteralArrayType(CharTy, Literal.GetNumStringChars());
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
Kind, Literal.Pascal, StrTy,
&StringTokLocs[0],
StringTokLocs.size());
if (Literal.getUDSuffix().empty())
return Lit;
// We're building a user-defined literal.
IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
SourceLocation UDSuffixLoc =
getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()],
Literal.getUDSuffixOffset());
// Make sure we're allowed user-defined literals here.
if (!UDLScope)
return ExprError(Diag(UDSuffixLoc, diag::err_invalid_string_udl));
// C++11 [lex.ext]p5: The literal L is treated as a call of the form
// operator "" X (str, len)
QualType SizeType = Context.getSizeType();
DeclarationName OpName =
Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
QualType ArgTy[] = {
Context.getArrayDecayedType(StrTy), SizeType
};
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, ArgTy,
/*AllowRaw*/ false, /*AllowTemplate*/ false,
/*AllowStringTemplate*/ true,
/*DiagnoseMissing*/ true)) {
case LOLR_Cooked: {
llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
StringTokLocs[0]);
Expr *Args[] = { Lit, LenArg };
return BuildLiteralOperatorCall(R, OpNameInfo, Args, StringTokLocs.back());
}
case LOLR_StringTemplate: {
TemplateArgumentListInfo ExplicitArgs;
unsigned CharBits = Context.getIntWidth(CharTy);
bool CharIsUnsigned = CharTy->isUnsignedIntegerType();
llvm::APSInt Value(CharBits, CharIsUnsigned);
TemplateArgument TypeArg(CharTy);
TemplateArgumentLocInfo TypeArgInfo(Context.getTrivialTypeSourceInfo(CharTy));
ExplicitArgs.addArgument(TemplateArgumentLoc(TypeArg, TypeArgInfo));
for (unsigned I = 0, N = Lit->getLength(); I != N; ++I) {
Value = Lit->getCodeUnit(I);
TemplateArgument Arg(Context, Value, CharTy);
TemplateArgumentLocInfo ArgInfo;
ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
}
return BuildLiteralOperatorCall(R, OpNameInfo, None, StringTokLocs.back(),
&ExplicitArgs);
}
case LOLR_Raw:
case LOLR_Template:
case LOLR_ErrorNoDiagnostic:
llvm_unreachable("unexpected literal operator lookup result");
case LOLR_Error:
return ExprError();
}
llvm_unreachable("unexpected literal operator lookup result");
}
DeclRefExpr *
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
SourceLocation Loc,
const CXXScopeSpec *SS) {
DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
}
DeclRefExpr *
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS, NamedDecl *FoundD,
SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo *TemplateArgs) {
NestedNameSpecifierLoc NNS =
SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc();
return BuildDeclRefExpr(D, Ty, VK, NameInfo, NNS, FoundD, TemplateKWLoc,
TemplateArgs);
}
NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) {
// A declaration named in an unevaluated operand never constitutes an odr-use.
if (isUnevaluatedContext())
return NOUR_Unevaluated;
// C++2a [basic.def.odr]p4:
// A variable x whose name appears as a potentially-evaluated expression e
// is odr-used by e unless [...] x is a reference that is usable in
// constant expressions.
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->getType()->isReferenceType() &&
!(getLangOpts().OpenMP && isOpenMPCapturedDecl(D)) &&
VD->isUsableInConstantExpressions(Context))
return NOUR_Constant;
}
// All remaining non-variable cases constitute an odr-use. For variables, we
// need to wait and see how the expression is used.
return NOUR_None;
}
/// BuildDeclRefExpr - Build an expression that references a
/// declaration that does not require a closure capture.
DeclRefExpr *
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
NestedNameSpecifierLoc NNS, NamedDecl *FoundD,
SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo *TemplateArgs) {
bool RefersToCapturedVariable =
isa<VarDecl>(D) &&
NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc());
DeclRefExpr *E = DeclRefExpr::Create(
Context, NNS, TemplateKWLoc, D, RefersToCapturedVariable, NameInfo, Ty,
VK, FoundD, TemplateArgs, getNonOdrUseReasonInCurrentContext(D));
MarkDeclRefReferenced(E);
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getBeginLoc()))
getCurFunction()->recordUseOfWeak(E);
FieldDecl *FD = dyn_cast<FieldDecl>(D);
if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D))
FD = IFD->getAnonField();
if (FD) {
UnusedPrivateFields.remove(FD);
// Just in case we're building an illegal pointer-to-member.
if (FD->isBitField())
E->setObjectKind(OK_BitField);
}
// C++ [expr.prim]/8: The expression [...] is a bit-field if the identifier
// designates a bit-field.
if (auto *BD = dyn_cast<BindingDecl>(D))
if (auto *BE = BD->getBinding())
E->setObjectKind(BE->getObjectKind());
return E;
}
/// Decomposes the given name into a DeclarationNameInfo, its location, and
/// possibly a list of template arguments.
///
/// If this produces template arguments, it is permitted to call
/// DecomposeTemplateName.
///
/// This actually loses a lot of source location information for
/// non-standard name kinds; we should consider preserving that in
/// some way.
void
Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
TemplateArgumentListInfo &Buffer,
DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *&TemplateArgs) {
if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId) {
Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
ASTTemplateArgsPtr TemplateArgsPtr(Id.TemplateId->getTemplateArgs(),
Id.TemplateId->NumArgs);
translateTemplateArguments(TemplateArgsPtr, Buffer);
TemplateName TName = Id.TemplateId->Template.get();
SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc;
NameInfo = Context.getNameForTemplate(TName, TNameLoc);
TemplateArgs = &Buffer;
} else {
NameInfo = GetNameFromUnqualifiedId(Id);
TemplateArgs = nullptr;
}
}
static void emitEmptyLookupTypoDiagnostic(
const TypoCorrection &TC, Sema &SemaRef, const CXXScopeSpec &SS,
DeclarationName Typo, SourceLocation TypoLoc, ArrayRef<Expr *> Args,
unsigned DiagnosticID, unsigned DiagnosticSuggestID) {
DeclContext *Ctx =
SS.isEmpty() ? nullptr : SemaRef.computeDeclContext(SS, false);
if (!TC) {
// Emit a special diagnostic for failed member lookups.
// FIXME: computing the declaration context might fail here (?)
if (Ctx)
SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << Ctx
<< SS.getRange();
else
SemaRef.Diag(TypoLoc, DiagnosticID) << Typo;
return;
}
std::string CorrectedStr = TC.getAsString(SemaRef.getLangOpts());
bool DroppedSpecifier =
TC.WillReplaceSpecifier() && Typo.getAsString() == CorrectedStr;
unsigned NoteID = TC.getCorrectionDeclAs<ImplicitParamDecl>()
? diag::note_implicit_param_decl
: diag::note_previous_decl;
if (!Ctx)
SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo,
SemaRef.PDiag(NoteID));
else
SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
<< Typo << Ctx << DroppedSpecifier
<< SS.getRange(),
SemaRef.PDiag(NoteID));
}
/// Diagnose an empty lookup.
///
/// \return false if new lookup candidates were found
bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
CorrectionCandidateCallback &CCC,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args, TypoExpr **Out) {
DeclarationName Name = R.getLookupName();
unsigned diagnostic = diag::err_undeclared_var_use;
unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest;
if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
diagnostic = diag::err_undeclared_use;
diagnostic_suggest = diag::err_undeclared_use_suggest;
}
// If the original lookup was an unqualified lookup, fake an
// unqualified lookup. This is useful when (for example) the
// original lookup would not have found something because it was a
// dependent name.
DeclContext *DC = SS.isEmpty() ? CurContext : nullptr;
while (DC) {
if (isa<CXXRecordDecl>(DC)) {
LookupQualifiedName(R, DC);
if (!R.empty()) {
// Don't give errors about ambiguities in this lookup.
R.suppressDiagnostics();
// During a default argument instantiation the CurContext points
// to a CXXMethodDecl; but we can't apply a this-> fixit inside a
// function parameter list, hence add an explicit check.
bool isDefaultArgument =
!CodeSynthesisContexts.empty() &&
CodeSynthesisContexts.back().Kind ==
CodeSynthesisContext::DefaultFunctionArgumentInstantiation;
CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
bool isInstance = CurMethod &&
CurMethod->isInstance() &&
DC == CurMethod->getParent() && !isDefaultArgument;
// Give a code modification hint to insert 'this->'.
// TODO: fixit for inserting 'Base<T>::' in the other cases.
// Actually quite difficult!
if (getLangOpts().MSVCCompat)
diagnostic = diag::ext_found_via_dependent_bases_lookup;
if (isInstance) {
Diag(R.getNameLoc(), diagnostic) << Name
<< FixItHint::CreateInsertion(R.getNameLoc(), "this->");
CheckCXXThisCapture(R.getNameLoc());
} else {
Diag(R.getNameLoc(), diagnostic) << Name;
}
// Do we really want to note all of these?
for (NamedDecl *D : R)
Diag(D->getLocation(), diag::note_dependent_var_use);
// Return true if we are inside a default argument instantiation
// and the found name refers to an instance member function, otherwise
// the function calling DiagnoseEmptyLookup will try to create an
// implicit member call and this is wrong for default argument.
if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) {
Diag(R.getNameLoc(), diag::err_member_call_without_object);
return true;
}
// Tell the callee to try to recover.
return false;
}
R.clear();
}
DC = DC->getLookupParent();
}
// We didn't find anything, so try to correct for a typo.
TypoCorrection Corrected;
if (S && Out) {
SourceLocation TypoLoc = R.getNameLoc();
assert(!ExplicitTemplateArgs &&
"Diagnosing an empty lookup with explicit template args!");
*Out = CorrectTypoDelayed(
R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC,
[=](const TypoCorrection &TC) {
emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args,
diagnostic, diagnostic_suggest);
},
nullptr, CTK_ErrorRecovery);
if (*Out)
return true;
} else if (S &&
(Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
S, &SS, CCC, CTK_ErrorRecovery))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
R.setLookupName(Corrected.getCorrection());
bool AcceptableWithRecovery = false;
bool AcceptableWithoutRecovery = false;
NamedDecl *ND = Corrected.getFoundDecl();
if (ND) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(R.getNameLoc(),
OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
for (NamedDecl *CD : Corrected) {
if (FunctionTemplateDecl *FTD =
dyn_cast<FunctionTemplateDecl>(CD))
AddTemplateOverloadCandidate(
FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs,
Args, OCS);
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD))
if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0)
AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none),
Args, OCS);
}
switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
case OR_Success:
ND = Best->FoundDecl;
Corrected.setCorrectionDecl(ND);
break;
default:
// FIXME: Arbitrarily pick the first declaration for the note.
Corrected.setCorrectionDecl(ND);
break;
}
}
R.addDecl(ND);
if (getLangOpts().CPlusPlus && ND->isCXXClassMember()) {
CXXRecordDecl *Record = nullptr;
if (Corrected.getCorrectionSpecifier()) {
const Type *Ty = Corrected.getCorrectionSpecifier()->getAsType();
Record = Ty->getAsCXXRecordDecl();
}
if (!Record)
Record = cast<CXXRecordDecl>(
ND->getDeclContext()->getRedeclContext());
R.setNamingClass(Record);
}
auto *UnderlyingND = ND->getUnderlyingDecl();
AcceptableWithRecovery = isa<ValueDecl>(UnderlyingND) ||
isa<FunctionTemplateDecl>(UnderlyingND);
// FIXME: If we ended up with a typo for a type name or
// Objective-C class name, we're in trouble because the parser
// is in the wrong place to recover. Suggest the typo
// correction, but don't make it a fix-it since we're not going
// to recover well anyway.
AcceptableWithoutRecovery = isa<TypeDecl>(UnderlyingND) ||
getAsTypeTemplateDecl(UnderlyingND) ||
isa<ObjCInterfaceDecl>(UnderlyingND);
} else {
// FIXME: We found a keyword. Suggest it, but don't provide a fix-it
// because we aren't able to recover.
AcceptableWithoutRecovery = true;
}
if (AcceptableWithRecovery || AcceptableWithoutRecovery) {
unsigned NoteID = Corrected.getCorrectionDeclAs<ImplicitParamDecl>()
? diag::note_implicit_param_decl
: diag::note_previous_decl;
if (SS.isEmpty())
diagnoseTypo(Corrected, PDiag(diagnostic_suggest) << Name,
PDiag(NoteID), AcceptableWithRecovery);
else
diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
<< Name << computeDeclContext(SS, false)
<< DroppedSpecifier << SS.getRange(),
PDiag(NoteID), AcceptableWithRecovery);
// Tell the callee whether to try to recover.
return !AcceptableWithRecovery;
}
}
R.clear();
// Emit a special diagnostic for failed member lookups.
// FIXME: computing the declaration context might fail here (?)
if (!SS.isEmpty()) {
Diag(R.getNameLoc(), diag::err_no_member)
<< Name << computeDeclContext(SS, false)
<< SS.getRange();
return true;
}
// Give up, we can't recover.
Diag(R.getNameLoc(), diagnostic) << Name;
return true;
}
/// In Microsoft mode, if we are inside a template class whose parent class has
/// dependent base classes, and we can't resolve an unqualified identifier, then
/// assume the identifier is a member of a dependent base class. We can only
/// recover successfully in static methods, instance methods, and other contexts
/// where 'this' is available. This doesn't precisely match MSVC's
/// instantiation model, but it's close enough.
static Expr *
recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
DeclarationNameInfo &NameInfo,
SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo *TemplateArgs) {
// Only try to recover from lookup into dependent bases in static methods or
// contexts where 'this' is available.
QualType ThisType = S.getCurrentThisType();
const CXXRecordDecl *RD = nullptr;
if (!ThisType.isNull())
RD = ThisType->getPointeeType()->getAsCXXRecordDecl();
else if (auto *MD = dyn_cast<CXXMethodDecl>(S.CurContext))
RD = MD->getParent();
if (!RD || !RD->hasAnyDependentBases())
return nullptr;
// Diagnose this as unqualified lookup into a dependent base class. If 'this'
// is available, suggest inserting 'this->' as a fixit.
SourceLocation Loc = NameInfo.getLoc();
auto DB = S.Diag(Loc, diag::ext_undeclared_unqual_id_with_dependent_base);
DB << NameInfo.getName() << RD;
if (!ThisType.isNull()) {
DB << FixItHint::CreateInsertion(Loc, "this->");
return CXXDependentScopeMemberExpr::Create(
Context, /*This=*/nullptr, ThisType, /*IsArrow=*/true,
/*Op=*/SourceLocation(), NestedNameSpecifierLoc(), TemplateKWLoc,
/*FirstQualifierFoundInScope=*/nullptr, NameInfo, TemplateArgs);
}
// Synthesize a fake NNS that points to the derived class. This will
// perform name lookup during template instantiation.
CXXScopeSpec SS;
auto *NNS =
NestedNameSpecifier::Create(Context, nullptr, true, RD->getTypeForDecl());
SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc));
return DependentScopeDeclRefExpr::Create(
Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
TemplateArgs);
}
ExprResult
Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
SourceLocation TemplateKWLoc, UnqualifiedId &Id,
bool HasTrailingLParen, bool IsAddressOfOperand,
CorrectionCandidateCallback *CCC,
bool IsInlineAsmIdentifier, Token *KeywordReplacement) {
assert(!(IsAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
if (SS.isInvalid())
return ExprError();
TemplateArgumentListInfo TemplateArgsBuffer;
// Decompose the UnqualifiedId into the following data.
DeclarationNameInfo NameInfo;
const TemplateArgumentListInfo *TemplateArgs;
DecomposeUnqualifiedId(Id, TemplateArgsBuffer, NameInfo, TemplateArgs);
DeclarationName Name = NameInfo.getName();
IdentifierInfo *II = Name.getAsIdentifierInfo();
SourceLocation NameLoc = NameInfo.getLoc();
if (II && II->isEditorPlaceholder()) {
// FIXME: When typed placeholders are supported we can create a typed
// placeholder expression node.
return ExprError();
}
// C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
// -- an identifier that was declared with a dependent type,
// (note: handled after lookup)
// -- a template-id that is dependent,
// (note: handled in BuildTemplateIdExpr)
// -- a conversion-function-id that specifies a dependent type,
// -- a nested-name-specifier that contains a class-name that
// names a dependent type.
// Determine whether this is a member of an unknown specialization;
// we need to handle these differently.
bool DependentID = false;
if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
Name.getCXXNameType()->isDependentType()) {
DependentID = true;
} else if (SS.isSet()) {
if (DeclContext *DC = computeDeclContext(SS, false)) {
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
} else {
DependentID = true;
}
}
if (DependentID)
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
IsAddressOfOperand, TemplateArgs);
// Perform the required lookup.
LookupResult R(*this, NameInfo,
(Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam)
? LookupObjCImplicitSelfParam
: LookupOrdinaryName);
if (TemplateKWLoc.isValid() || TemplateArgs) {
// Lookup the template name again to correctly establish the context in
// which it was found. This is really unfortunate as we already did the
// lookup to determine that it was a template name in the first place. If
// this becomes a performance hit, we can work harder to preserve those
// results until we get here but it's likely not worth it.
bool MemberOfUnknownSpecialization;
AssumedTemplateKind AssumedTemplate;
if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
MemberOfUnknownSpecialization, TemplateKWLoc,
&AssumedTemplate))
return ExprError();
if (MemberOfUnknownSpecialization ||
(R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
IsAddressOfOperand, TemplateArgs);
} else {
bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl();
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
// If the result might be in a dependent base class, this is a dependent
// id-expression.
if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
IsAddressOfOperand, TemplateArgs);
// If this reference is in an Objective-C method, then we need to do
// some special Objective-C lookup, too.
if (IvarLookupFollowUp) {
ExprResult E(LookupInObjCMethod(R, S, II, true));
if (E.isInvalid())
return ExprError();
if (Expr *Ex = E.getAs<Expr>())
return Ex;
}
}
if (R.isAmbiguous())
return ExprError();
// This could be an implicitly declared function reference (legal in C90,
// extension in C99, forbidden in C++).
if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
if (D) R.addDecl(D);
}
// Determine whether this name might be a candidate for
// argument-dependent lookup.
bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
if (R.empty() && !ADL) {
if (SS.isEmpty() && getLangOpts().MSVCCompat) {
if (Expr *E = recoverFromMSUnqualifiedLookup(*this, Context, NameInfo,
TemplateKWLoc, TemplateArgs))
return E;
}
// Don't diagnose an empty lookup for inline assembly.
if (IsInlineAsmIdentifier)
return ExprError();
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
TypoExpr *TE = nullptr;
DefaultFilterCCC DefaultValidator(II, SS.isValid() ? SS.getScopeRep()
: nullptr);
DefaultValidator.IsAddressOfOperand = IsAddressOfOperand;
assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
"Typo correction callback misconfigured");
if (CCC) {
// Make sure the callback knows what the typo being diagnosed is.
CCC->setTypoName(II);
if (SS.isValid())
CCC->setTypoNNS(SS.getScopeRep());
}
// FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for
// a template name, but we happen to have always already looked up the name
// before we get here if it must be a template name.
if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator, nullptr,
None, &TE)) {
if (TE && KeywordReplacement) {
auto &State = getTypoExprState(TE);
auto BestTC = State.Consumer->getNextCorrection();
if (BestTC.isKeyword()) {
auto *II = BestTC.getCorrectionAsIdentifierInfo();
if (State.DiagHandler)
State.DiagHandler(BestTC);
KeywordReplacement->startToken();
KeywordReplacement->setKind(II->getTokenID());
KeywordReplacement->setIdentifierInfo(II);
KeywordReplacement->setLocation(BestTC.getCorrectionRange().getBegin());
// Clean up the state associated with the TypoExpr, since it has
// now been diagnosed (without a call to CorrectDelayedTyposInExpr).
clearDelayedTypo(TE);
// Signal that a correction to a keyword was performed by returning a
// valid-but-null ExprResult.
return (Expr*)nullptr;
}
State.Consumer->resetCorrectionStream();
}
return TE ? TE : ExprError();
}
assert(!R.empty() &&
"DiagnoseEmptyLookup returned false but added no results");
// If we found an Objective-C instance variable, let
// LookupInObjCMethod build the appropriate expression to
// reference the ivar.
if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
R.clear();
ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
// In a hopelessly buggy code, Objective-C instance variable
// lookup fails and no expression will be built to reference it.
if (!E.isInvalid() && !E.get())
return ExprError();
return E;
}
}
// This is guaranteed from this point on.
assert(!R.empty() || ADL);
// Check whether this might be a C++ implicit instance member access.
// C++ [class.mfct.non-static]p3:
// When an id-expression that is not part of a class member access
// syntax and not used to form a pointer to member is used in the
// body of a non-static member function of class X, if name lookup
// resolves the name in the id-expression to a non-static non-type
// member of some class C, the id-expression is transformed into a
// class member access expression using (*this) as the
// postfix-expression to the left of the . operator.
//
// But we don't actually need to do this for '&' operands if R
// resolved to a function or overloaded function set, because the
// expression is ill-formed if it actually works out to be a
// non-static member function:
//
// C++ [expr.ref]p4:
// Otherwise, if E1.E2 refers to a non-static member function. . .
// [t]he expression can be used only as the left-hand operand of a
// member function call.
//
// There are other safeguards against such uses, but it's important
// to get this right here so that we don't end up making a
// spuriously dependent expression if we're inside a dependent
// instance method.
if (!R.empty() && (*R.begin())->isCXXClassMember()) {
bool MightBeImplicitMember;
if (!IsAddressOfOperand)
MightBeImplicitMember = true;
else if (!SS.isEmpty())
MightBeImplicitMember = false;
else if (R.isOverloadedResult())
MightBeImplicitMember = false;
else if (R.isUnresolvableResult())
MightBeImplicitMember = true;
else
MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
isa<IndirectFieldDecl>(R.getFoundDecl()) ||
isa<MSPropertyDecl>(R.getFoundDecl());
if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
R, TemplateArgs, S);
}
if (TemplateArgs || TemplateKWLoc.isValid()) {
// In C++1y, if this is a variable template id, then check it
// in BuildTemplateIdExpr().
// The single lookup result must be a variable template declaration.
if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId && Id.TemplateId &&
Id.TemplateId->Kind == TNK_Var_template) {
assert(R.getAsSingle<VarTemplateDecl>() &&
"There should only be one declaration found.");
}
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs);
}
return BuildDeclarationNameExpr(SS, R, ADL);
}
/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
/// declaration name, generally during template instantiation.
/// There's a large number of things which don't need to be done along
/// this path.
ExprResult Sema::BuildQualifiedDeclarationNameExpr(
CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo,
bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) {
DeclContext *DC = computeDeclContext(SS, false);
if (!DC)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
NameInfo, /*TemplateArgs=*/nullptr);
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
LookupResult R(*this, NameInfo, LookupOrdinaryName);
LookupQualifiedName(R, DC);
if (R.isAmbiguous())
return ExprError();
if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
NameInfo, /*TemplateArgs=*/nullptr);
if (R.empty()) {
Diag(NameInfo.getLoc(), diag::err_no_member)
<< NameInfo.getName() << DC << SS.getRange();
return ExprError();
}
if (const TypeDecl *TD = R.getAsSingle<TypeDecl>()) {
// Diagnose a missing typename if this resolved unambiguously to a type in
// a dependent context. If we can recover with a type, downgrade this to
// a warning in Microsoft compatibility mode.
unsigned DiagID = diag::err_typename_missing;
if (RecoveryTSI && getLangOpts().MSVCCompat)
DiagID = diag::ext_typename_missing;
SourceLocation Loc = SS.getBeginLoc();
auto D = Diag(Loc, DiagID);
D << SS.getScopeRep() << NameInfo.getName().getAsString()
<< SourceRange(Loc, NameInfo.getEndLoc());
// Don't recover if the caller isn't expecting us to or if we're in a SFINAE
// context.
if (!RecoveryTSI)
return ExprError();
// Only issue the fixit if we're prepared to recover.
D << FixItHint::CreateInsertion(Loc, "typename ");
// Recover by pretending this was an elaborated type.
QualType Ty = Context.getTypeDeclType(TD);
TypeLocBuilder TLB;
TLB.pushTypeSpec(Ty).setNameLoc(NameInfo.getLoc());
QualType ET = getElaboratedType(ETK_None, SS, Ty);
ElaboratedTypeLoc QTL = TLB.push<ElaboratedTypeLoc>(ET);
QTL.setElaboratedKeywordLoc(SourceLocation());
QTL.setQualifierLoc(SS.getWithLocInContext(Context));
*RecoveryTSI = TLB.getTypeSourceInfo(Context, ET);
return ExprEmpty();
}
// Defend against this resolving to an implicit member access. We usually
// won't get here if this might be a legitimate a class member (we end up in
// BuildMemberReferenceExpr instead), but this can be valid if we're forming
// a pointer-to-member or in an unevaluated context in C++11.
if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand)
return BuildPossibleImplicitMemberExpr(SS,
/*TemplateKWLoc=*/SourceLocation(),
R, /*TemplateArgs=*/nullptr, S);
return BuildDeclarationNameExpr(SS, R, /* ADL */ false);
}
/// The parser has read a name in, and Sema has detected that we're currently
/// inside an ObjC method. Perform some additional checks and determine if we
/// should form a reference to an ivar.
///
/// Ideally, most of this would be done by lookup, but there's
/// actually quite a lot of extra work involved.
DeclResult Sema::LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
IdentifierInfo *II) {
SourceLocation Loc = Lookup.getNameLoc();
ObjCMethodDecl *CurMethod = getCurMethodDecl();
// Check for error condition which is already reported.
if (!CurMethod)
return DeclResult(true);
// There are two cases to handle here. 1) scoped lookup could have failed,
// in which case we should look for an ivar. 2) scoped lookup could have
// found a decl, but that decl is outside the current instance method (i.e.
// a global variable). In these two cases, we do a lookup for an ivar with
// this name, if the lookup sucedes, we replace it our current decl.
// If we're in a class method, we don't normally want to look for
// ivars. But if we don't find anything else, and there's an
// ivar, that's an error.
bool IsClassMethod = CurMethod->isClassMethod();
bool LookForIvars;
if (Lookup.empty())
LookForIvars = true;
else if (IsClassMethod)
LookForIvars = false;
else
LookForIvars = (Lookup.isSingleResult() &&
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
ObjCInterfaceDecl *IFace = nullptr;
if (LookForIvars) {
IFace = CurMethod->getClassInterface();
ObjCInterfaceDecl *ClassDeclared;
ObjCIvarDecl *IV = nullptr;
if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {
// Diagnose using an ivar in a class method.
if (IsClassMethod) {
Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName();
return DeclResult(true);
}
// Diagnose the use of an ivar outside of the declaring class.
if (IV->getAccessControl() == ObjCIvarDecl::Private &&
!declaresSameEntity(ClassDeclared, IFace) &&
!getLangOpts().DebuggerSupport)
Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName();
// Success.
return IV;
}
} else if (CurMethod->isInstanceMethod()) {
// We should warn if a local variable hides an ivar.
if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) {
ObjCInterfaceDecl *ClassDeclared;
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
if (IV->getAccessControl() != ObjCIvarDecl::Private ||
declaresSameEntity(IFace, ClassDeclared))
Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
}
}
} else if (Lookup.isSingleResult() &&
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {
// If accessing a stand-alone ivar in a class method, this is an error.
if (const ObjCIvarDecl *IV =
dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl())) {
Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName();
return DeclResult(true);
}
}
// Didn't encounter an error, didn't find an ivar.
return DeclResult(false);
}
ExprResult Sema::BuildIvarRefExpr(Scope *S, SourceLocation Loc,
ObjCIvarDecl *IV) {
ObjCMethodDecl *CurMethod = getCurMethodDecl();
assert(CurMethod && CurMethod->isInstanceMethod() &&
"should not reference ivar from this context");
ObjCInterfaceDecl *IFace = CurMethod->getClassInterface();
assert(IFace && "should not reference ivar from this context");
// If we're referencing an invalid decl, just return this as a silent
// error node. The error diagnostic was already emitted on the decl.
if (IV->isInvalidDecl())
return ExprError();
// Check if referencing a field with __attribute__((deprecated)).
if (DiagnoseUseOfDecl(IV, Loc))
return ExprError();
// FIXME: This should use a new expr for a direct reference, don't
// turn this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
UnqualifiedId SelfName;
SelfName.setIdentifier(&II, SourceLocation());
SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
CXXScopeSpec SelfScopeSpec;
SourceLocation TemplateKWLoc;
ExprResult SelfExpr =
ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName,
/*HasTrailingLParen=*/false,
/*IsAddressOfOperand=*/false);
if (SelfExpr.isInvalid())
return ExprError();
SelfExpr = DefaultLvalueConversion(SelfExpr.get());
if (SelfExpr.isInvalid())
return ExprError();
MarkAnyDeclReferenced(Loc, IV, true);
ObjCMethodFamily MF = CurMethod->getMethodFamily();
if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
!IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
ObjCIvarRefExpr *Result = new (Context)
ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc,
IV->getLocation(), SelfExpr.get(), true, true);
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
if (!isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
getCurFunction()->recordUseOfWeak(Result);
}
if (getLangOpts().ObjCAutoRefCount)
if (const BlockDecl *BD = CurContext->getInnermostBlockDecl())
ImplicitlyRetainedSelfLocs.push_back({Loc, BD});
return Result;
}
/// The parser has read a name in, and Sema has detected that we're currently
/// inside an ObjC method. Perform some additional checks and determine if we
/// should form a reference to an ivar. If so, build an expression referencing
/// that ivar.
ExprResult
Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IdentifierInfo *II, bool AllowBuiltinCreation) {
// FIXME: Integrate this lookup step into LookupParsedName.
DeclResult Ivar = LookupIvarInObjCMethod(Lookup, S, II);
if (Ivar.isInvalid())
return ExprError();
if (Ivar.isUsable())
return BuildIvarRefExpr(S, Lookup.getNameLoc(),
cast<ObjCIvarDecl>(Ivar.get()));
if (Lookup.empty() && II && AllowBuiltinCreation)
LookupBuiltin(Lookup);
// Sentinel value saying that we didn't do anything special.
return ExprResult(false);
}
/// Cast a base object to a member's actual type.
///
/// Logically this happens in three phases:
///
/// * First we cast from the base type to the naming class.
/// The naming class is the class into which we were looking
/// when we found the member; it's the qualifier type if a
/// qualifier was provided, and otherwise it's the base type.
///
/// * Next we cast from the naming class to the declaring class.
/// If the member we found was brought into a class's scope by
/// a using declaration, this is that class; otherwise it's
/// the class declaring the member.
///
/// * Finally we cast from the declaring class to the "true"
/// declaring class of the member. This conversion does not
/// obey access control.
ExprResult
Sema::PerformObjectMemberConversion(Expr *From,
NestedNameSpecifier *Qualifier,
NamedDecl *FoundDecl,
NamedDecl *Member) {
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
if (!RD)
return From;
QualType DestRecordType;
QualType DestType;
QualType FromRecordType;
QualType FromType = From->getType();
bool PointerConversions = false;
if (isa<FieldDecl>(Member)) {
DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD));
auto FromPtrType = FromType->getAs<PointerType>();
DestRecordType = Context.getAddrSpaceQualType(
DestRecordType, FromPtrType
? FromType->getPointeeType().getAddressSpace()
: FromType.getAddressSpace());
if (FromPtrType) {
DestType = Context.getPointerType(DestRecordType);
FromRecordType = FromPtrType->getPointeeType();
PointerConversions = true;
} else {
DestType = DestRecordType;
FromRecordType = FromType;
}
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) {
if (Method->isStatic())
return From;
DestType = Method->getThisType();
DestRecordType = DestType->getPointeeType();
if (FromType->getAs<PointerType>()) {
FromRecordType = FromType->getPointeeType();
PointerConversions = true;
} else {
FromRecordType = FromType;
DestType = DestRecordType;