summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp2490
1 files changed, 1563 insertions, 927 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index a9179fd..e1f65f4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -15,6 +15,7 @@
#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"
@@ -140,11 +141,13 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
return Result;
}
-/// \brief Emit a note explaining that this function is deleted or unavailable.
+/// \brief 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->isDeletedAsWritten()) {
+ 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);
@@ -158,8 +161,23 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
return;
}
+ if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Decl)) {
+ if (CXXConstructorDecl *BaseCD =
+ const_cast<CXXConstructorDecl*>(CD->getInheritedConstructor())) {
+ Diag(Decl->getLocation(), diag::note_inherited_deleted_here);
+ if (BaseCD->isDeleted()) {
+ NoteDeletedFunction(BaseCD);
+ } else {
+ // FIXME: An explanation of why exactly it can't be inherited
+ // would be nice.
+ Diag(BaseCD->getLocation(), diag::note_cannot_inherit);
+ }
+ return;
+ }
+ }
+
Diag(Decl->getLocation(), diag::note_unavailable_here)
- << 1 << Decl->isDeleted();
+ << 1 << true;
}
/// \brief Determine whether a FunctionDecl was ever declared with an
@@ -197,11 +215,11 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
return;
if (!Current->isInlined())
return;
- if (Current->getLinkage() != ExternalLinkage)
+ if (!Current->isExternallyVisible())
return;
-
+
// Check if the decl has internal linkage.
- if (D->getLinkage() != InternalLinkage)
+ if (D->getFormalLinkage() != InternalLinkage)
return;
// Downgrade from ExtWarn to Extension if
@@ -212,7 +230,7 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
// 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().isFromMainFile(Loc);
+ bool DowngradeWarning = S.getSourceManager().isInMainFile(Loc);
if (!DowngradeWarning && UsedFn)
DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr<ConstAttr>();
@@ -228,7 +246,7 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
}
void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
- const FunctionDecl *First = Cur->getFirstDeclaration();
+ const FunctionDecl *First = Cur->getFirstDecl();
// Suggest "static" on the function, if possible.
if (!hasAnyExplicitStorageClass(First)) {
@@ -255,7 +273,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
- llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator
+ SuppressedDiagnosticsMap::iterator
Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
if (Pos != SuppressedDiagnostics.end()) {
SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
@@ -316,7 +334,7 @@ std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
/// if so, it checks that the requirements of the sentinel are
/// satisfied.
void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
- Expr **args, unsigned numArgs) {
+ ArrayRef<Expr *> Args) {
const SentinelAttr *attr = D->getAttr<SentinelAttr>();
if (!attr)
return;
@@ -370,14 +388,14 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
// If there aren't enough arguments for all the formal parameters,
// the sentinel, and the args after the sentinel, complain.
- if (numArgs < numFormalParams + numArgsAfterSentinel + 1) {
+ if (Args.size() < numFormalParams + numArgsAfterSentinel + 1) {
Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
- Diag(D->getLocation(), diag::note_sentinel_here) << calleeType;
+ Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
return;
}
// Otherwise, find the sentinel expression.
- Expr *sentinelExpr = args[numArgs - numArgsAfterSentinel - 1];
+ Expr *sentinelExpr = Args[Args.size() - numArgsAfterSentinel - 1];
if (!sentinelExpr) return;
if (sentinelExpr->isValueDependent()) return;
if (Context.isSentinelNullExpr(sentinelExpr)) return;
@@ -398,12 +416,12 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
NullValue = "(void*) 0";
if (MissingNilLoc.isInvalid())
- Diag(Loc, diag::warn_missing_sentinel) << calleeType;
+ Diag(Loc, diag::warn_missing_sentinel) << int(calleeType);
else
Diag(MissingNilLoc, diag::warn_missing_sentinel)
- << calleeType
+ << int(calleeType)
<< FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue);
- Diag(D->getLocation(), diag::note_sentinel_here) << calleeType;
+ Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
}
SourceRange Sema::getExprRange(Expr *E) const {
@@ -725,6 +743,17 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
/// 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;
@@ -747,35 +776,50 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType())
return VAK_Valid;
- return VAK_Invalid;
+
+ if (Ty->isObjCObjectType())
+ return VAK_Invalid;
+
+ // FIXME: In C++11, these cases are conditionally-supported, meaning we're
+ // permitted to reject them. We should consider doing so.
+ return VAK_Undefined;
}
-bool Sema::variadicArgumentPODCheck(const Expr *E, VariadicCallType CT) {
+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();
+ const QualType &Ty = E->getType();
+ VarArgKind VAK = isValidVarArgType(Ty);
// Complain about passing non-POD types through varargs.
- switch (isValidVarArgType(Ty)) {
+ switch (VAK) {
case VAK_Valid:
break;
+
case VAK_ValidInCXX11:
- DiagRuntimeBehavior(E->getLocStart(), 0,
+ DiagRuntimeBehavior(
+ E->getLocStart(), 0,
PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
- << E->getType() << CT);
+ << E->getType() << CT);
break;
- case VAK_Invalid: {
- if (Ty->isObjCObjectType())
- return DiagRuntimeBehavior(E->getLocStart(), 0,
- PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
- << Ty << CT);
- return DiagRuntimeBehavior(E->getLocStart(), 0,
- PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
- << getLangOpts().CPlusPlus11 << Ty << CT);
- }
+ case VAK_Undefined:
+ DiagRuntimeBehavior(
+ E->getLocStart(), 0,
+ PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
+ << getLangOpts().CPlusPlus11 << Ty << CT);
+ break;
+
+ case VAK_Invalid:
+ if (Ty->isObjCObjectType())
+ DiagRuntimeBehavior(
+ E->getLocStart(), 0,
+ PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
+ << Ty << CT);
+ else
+ Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg)
+ << isa<InitListExpr>(E) << Ty << CT;
+ break;
}
- // c++ rules are enforced elsewhere.
- return false;
}
/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
@@ -805,7 +849,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
// Diagnostics regarding non-POD argument types are
// emitted along with format string checking in Sema::CheckFunctionCall().
- if (isValidVarArgType(E->getType()) == VAK_Invalid) {
+ if (isValidVarArgType(E->getType()) == VAK_Undefined) {
// Turn this into a trap.
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
@@ -1230,25 +1274,23 @@ Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
- MultiTypeArg ArgTypes,
- MultiExprArg ArgExprs) {
+ ArrayRef<ParsedType> ArgTypes,
+ ArrayRef<Expr *> ArgExprs) {
unsigned NumAssocs = ArgTypes.size();
assert(NumAssocs == ArgExprs.size());
- ParsedType *ParsedTypes = ArgTypes.data();
- Expr **Exprs = ArgExprs.data();
-
TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs];
for (unsigned i = 0; i < NumAssocs; ++i) {
- if (ParsedTypes[i])
- (void) GetTypeFromParser(ParsedTypes[i], &Types[i]);
+ if (ArgTypes[i])
+ (void) GetTypeFromParser(ArgTypes[i], &Types[i]);
else
Types[i] = 0;
}
ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
- ControllingExpr, Types, Exprs,
- NumAssocs);
+ ControllingExpr,
+ llvm::makeArrayRef(Types, NumAssocs),
+ ArgExprs);
delete [] Types;
return ER;
}
@@ -1258,9 +1300,10 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
- TypeSourceInfo **Types,
- Expr **Exprs,
- unsigned NumAssocs) {
+ ArrayRef<TypeSourceInfo *> Types,
+ ArrayRef<Expr *> Exprs) {
+ unsigned NumAssocs = Types.size();
+ assert(NumAssocs == Exprs.size());
if (ControllingExpr->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(ControllingExpr);
if (result.isInvalid()) return ExprError();
@@ -1328,8 +1371,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
if (IsResultDependent)
return Owned(new (Context) GenericSelectionExpr(
Context, KeyLoc, ControllingExpr,
- llvm::makeArrayRef(Types, NumAssocs),
- llvm::makeArrayRef(Exprs, NumAssocs),
+ Types, Exprs,
DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack));
SmallVector<unsigned, 1> CompatIndices;
@@ -1352,7 +1394,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match)
<< ControllingExpr->getSourceRange() << ControllingExpr->getType()
<< (unsigned) CompatIndices.size();
- for (SmallVector<unsigned, 1>::iterator I = CompatIndices.begin(),
+ for (SmallVectorImpl<unsigned>::iterator I = CompatIndices.begin(),
E = CompatIndices.end(); I != E; ++I) {
Diag(Types[*I]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
@@ -1384,8 +1426,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
return Owned(new (Context) GenericSelectionExpr(
Context, KeyLoc, ControllingExpr,
- llvm::makeArrayRef(Types, NumAssocs),
- llvm::makeArrayRef(Exprs, NumAssocs),
+ Types, Exprs,
DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack,
ResultIndex));
}
@@ -1421,7 +1462,8 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
- /*AllowRawAndTemplate*/false) == Sema::LOLR_Error)
+ /*AllowRaw*/false, /*AllowTemplate*/false,
+ /*AllowStringTemplate*/false) == Sema::LOLR_Error)
return ExprError();
return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);
@@ -1446,36 +1488,39 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
for (unsigned i = 0; i != NumStringToks; ++i)
StringTokLocs.push_back(StringToks[i].getLocation());
- QualType StrTy = Context.CharTy;
- if (Literal.isWide())
- StrTy = Context.getWCharType();
- else if (Literal.isUTF16())
- StrTy = Context.Char16Ty;
- else if (Literal.isUTF32())
- StrTy = Context.Char32Ty;
- else if (Literal.isPascal())
- StrTy = Context.UnsignedCharTy;
-
+ QualType CharTy = Context.CharTy;
StringLiteral::StringKind Kind = StringLiteral::Ascii;
- if (Literal.isWide())
+ if (Literal.isWide()) {
+ CharTy = Context.getWideCharType();
Kind = StringLiteral::Wide;
- else if (Literal.isUTF8())
+ } else if (Literal.isUTF8()) {
Kind = StringLiteral::UTF8;
- else if (Literal.isUTF16())
+ } else if (Literal.isUTF16()) {
+ CharTy = Context.Char16Ty;
Kind = StringLiteral::UTF16;
- else if (Literal.isUTF32())
+ } else if (Literal.isUTF32()) {
+ CharTy = Context.Char32Ty;
Kind = StringLiteral::UTF32;
+ } else if (Literal.isPascal()) {
+ CharTy = Context.UnsignedCharTy;
+ }
+ QualType CharTyConst = CharTy;
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
- StrTy.addConst();
+ CharTyConst.addConst();
// Get an array type for the string, according to C99 6.4.5. This includes
// the nul terminator character as well as the string length for pascal
// strings.
- StrTy = Context.getConstantArrayType(StrTy,
+ QualType StrTy = Context.getConstantArrayType(CharTyConst,
llvm::APInt(32, Literal.GetNumStringChars()+1),
- ArrayType::Normal, 0);
+ ArrayType::Normal, 0);
+
+ // OpenCL v1.1 s6.5.3: a string literal is in the constant address space.
+ if (getLangOpts().OpenCL) {
+ StrTy = Context.getAddrSpaceQualType(StrTy, LangAS::opencl_constant);
+ }
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
@@ -1498,12 +1543,57 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
// C++11 [lex.ext]p5: The literal L is treated as a call of the form
// operator "" X (str, len)
QualType SizeType = Context.getSizeType();
- llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
- IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
- StringTokLocs[0]);
- Expr *Args[] = { Lit, LenArg };
- return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc,
- Args, StringTokLocs.back());
+
+ 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)) {
+
+ 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:
+ llvm_unreachable("unexpected literal operator lookup result");
+ case LOLR_Error:
+ return ExprError();
+ }
+ llvm_unreachable("unexpected literal operator lookup result");
}
ExprResult
@@ -1519,7 +1609,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
ExprResult
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
- const CXXScopeSpec *SS, NamedDecl *FoundD) {
+ const CXXScopeSpec *SS, NamedDecl *FoundD,
+ const TemplateArgumentListInfo *TemplateArgs) {
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) {
@@ -1536,14 +1627,28 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
bool refersToEnclosingScope =
(CurContext != D->getDeclContext() &&
- D->getDeclContext()->isFunctionOrMethod());
-
- DeclRefExpr *E = DeclRefExpr::Create(Context,
- SS ? SS->getWithLocInContext(Context)
- : NestedNameSpecifierLoc(),
- SourceLocation(),
- D, refersToEnclosingScope,
- NameInfo, Ty, VK, FoundD);
+ D->getDeclContext()->isFunctionOrMethod()) ||
+ (isa<VarDecl>(D) &&
+ cast<VarDecl>(D)->isInitCapture());
+
+ DeclRefExpr *E;
+ if (isa<VarTemplateSpecializationDecl>(D)) {
+ VarTemplateSpecializationDecl *VarSpec =
+ cast<VarTemplateSpecializationDecl>(D);
+
+ E = DeclRefExpr::Create(
+ Context,
+ SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+ VarSpec->getTemplateKeywordLoc(), D, refersToEnclosingScope,
+ NameInfo.getLoc(), Ty, VK, FoundD, TemplateArgs);
+ } else {
+ assert(!TemplateArgs && "No template arguments for non-variable"
+ " template specialization referrences");
+ E = DeclRefExpr::Create(
+ Context,
+ SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+ SourceLocation(), D, refersToEnclosingScope, NameInfo, Ty, VK, FoundD);
+ }
MarkDeclRefReferenced(E);
@@ -1553,7 +1658,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
E->getLocStart());
if (Level != DiagnosticsEngine::Ignored)
- getCurFunction()->recordUseOfWeak(E);
+ recordUseOfEvaluatedWeak(E);
}
// Just in case we're building an illegal pointer-to-member.
@@ -1602,7 +1707,7 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
CorrectionCandidateCallback &CCC,
TemplateArgumentListInfo *ExplicitTemplateArgs,
- llvm::ArrayRef<Expr *> Args) {
+ ArrayRef<Expr *> Args) {
DeclarationName Name = R.getLookupName();
unsigned diagnostic = diag::err_undeclared_var_use;
@@ -1722,10 +1827,14 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
S, &SS, CCC))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+ bool DroppedSpecifier =
+ Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
R.setLookupName(Corrected.getCorrection());
- if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+ bool AcceptableWithRecovery = false;
+ bool AcceptableWithoutRecovery = false;
+ NamedDecl *ND = Corrected.getCorrectionDecl();
+ if (ND) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(R.getNameLoc());
OverloadCandidateSet::iterator Best;
@@ -1743,63 +1852,49 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
Args, OCS);
}
switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
- case OR_Success:
- ND = Best->Function;
- break;
- default:
- break;
+ case OR_Success:
+ ND = Best->Function;
+ Corrected.setCorrectionDecl(ND);
+ break;
+ default:
+ // FIXME: Arbitrarily pick the first declaration for the note.
+ Corrected.setCorrectionDecl(ND);
+ break;
}
}
R.addDecl(ND);
- if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
- if (SS.isEmpty())
- Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr
- << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
- else
- Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- unsigned diag = isa<ImplicitParamDecl>(ND)
- ? diag::note_implicit_param_decl
- : diag::note_previous_decl;
-
- Diag(ND->getLocation(), diag)
- << CorrectedQuotedStr;
-
- // Tell the callee to try to recover.
- return false;
- }
-
- if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) {
- // 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.
- if (SS.isEmpty())
- Diag(R.getNameLoc(), diagnostic_suggest)
- << Name << CorrectedQuotedStr;
- else
- Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange();
-
- // Don't try to recover; it won't work.
- return true;
- }
+ AcceptableWithRecovery =
+ isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND);
+ // 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>(ND) || isa<ObjCInterfaceDecl>(ND);
} 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.getCorrectionDecl() &&
+ isa<ImplicitParamDecl>(Corrected.getCorrectionDecl()))
+ ? diag::note_implicit_param_decl
+ : diag::note_previous_decl;
if (SS.isEmpty())
- Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr;
+ diagnoseTypo(Corrected, PDiag(diagnostic_suggest) << Name,
+ PDiag(NoteID), AcceptableWithRecovery);
else
- Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange();
- return true;
+ 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();
@@ -1824,10 +1919,10 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
UnqualifiedId &Id,
bool HasTrailingLParen,
bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC) {
+ CorrectionCandidateCallback *CCC,
+ bool IsInlineAsmIdentifier) {
assert(!(IsAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
-
if (SS.isInvalid())
return ExprError();
@@ -1918,6 +2013,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
if (R.empty() && !ADL) {
+
// Otherwise, this could be an implicitly declared function reference (legal
// in C90, extension in C99, forbidden in C++).
if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
@@ -1930,16 +2026,32 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
if (R.empty()) {
// In Microsoft mode, if we are inside a template class member function
// whose parent class has dependent base classes, and we can't resolve
- // an identifier, then assume the identifier is type dependent. The
- // goal is to postpone name lookup to instantiation time to be able to
- // search into the type dependent base classes.
+ // an identifier, then assume the identifier is a member of a dependent
+ // base class. The goal is to postpone name lookup to instantiation time
+ // to be able to search into the type dependent base classes.
+ // FIXME: If we want 100% compatibility with MSVC, we will have delay all
+ // unqualified name lookup. Any name lookup during template parsing means
+ // clang might find something that MSVC doesn't. For now, we only handle
+ // the common case of members of a dependent base class.
if (getLangOpts().MicrosoftMode) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
- if (MD && MD->getParent()->hasAnyDependentBases())
- return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
- IsAddressOfOperand, TemplateArgs);
+ if (MD && MD->isInstance() && MD->getParent()->hasAnyDependentBases()) {
+ assert(SS.isEmpty() && "qualifiers should be already handled");
+ QualType ThisType = MD->getThisType(Context);
+ // Since the 'this' expression is synthesized, we don't need to
+ // perform the double-lookup check.
+ NamedDecl *FirstQualifierInScope = 0;
+ return Owned(CXXDependentScopeMemberExpr::Create(
+ Context, /*This=*/0, ThisType, /*IsArrow=*/true,
+ /*Op=*/SourceLocation(), SS.getWithLocInContext(Context),
+ TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs));
+ }
}
+ // Don't diagnose an empty lookup for inline assmebly.
+ if (IsInlineAsmIdentifier)
+ return ExprError();
+
CorrectionCandidateCallback DefaultValidator;
if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator))
return ExprError();
@@ -2001,15 +2113,27 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
MightBeImplicitMember = true;
else
MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
- isa<IndirectFieldDecl>(R.getFoundDecl());
+ isa<IndirectFieldDecl>(R.getFoundDecl()) ||
+ isa<MSPropertyDecl>(R.getFoundDecl());
if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
R, TemplateArgs);
}
- if (TemplateArgs || TemplateKWLoc.isValid())
+ 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() == UnqualifiedId::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);
}
@@ -2139,6 +2263,14 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
return ExprError();
MarkAnyDeclReferenced(Loc, IV, true);
+ if (!IV->getBackingIvarReferencedInAccessor()) {
+ // Mark this ivar 'referenced' in this method, if it is a backing ivar
+ // of a property and current method is one of its property accessor.
+ const ObjCPropertyDecl *PDecl;
+ const ObjCIvarDecl *BIV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
+ if (BIV && BIV == IV)
+ IV->setBackingIvarReferencedInAccessor(true);
+ }
ObjCMethodFamily MF = CurMethod->getMethodFamily();
if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
@@ -2155,7 +2287,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
DiagnosticsEngine::Level Level =
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc);
if (Level != DiagnosticsEngine::Ignored)
- getCurFunction()->recordUseOfWeak(Result);
+ recordUseOfEvaluatedWeak(Result);
}
if (CurContext->isClosure())
Diag(Loc, diag::warn_implicitly_retains_self)
@@ -2289,9 +2421,8 @@ Sema::PerformObjectMemberConversion(Expr *From,
// x = 17; // error: ambiguous base subobjects
// Derived1::x = 17; // okay, pick the Base subobject of Derived1
// }
- if (Qualifier) {
+ if (Qualifier && Qualifier->getAsType()) {
QualType QType = QualType(Qualifier->getAsType(), 0);
- assert(!QType.isNull() && "lookup done with dependent qualifier?");
assert(QType->isRecordType() && "lookup done with non-record type");
QualType QRecordType = QualType(QType->getAs<RecordType>(), 0);
@@ -2400,7 +2531,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
// turn off ADL anyway).
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
- else if (D->getDeclContext()->isFunctionOrMethod())
+ else if (D->getLexicalDeclContext()->isFunctionOrMethod())
return false;
// C++0x [basic.lookup.argdep]p3:
@@ -2477,10 +2608,9 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
}
/// \brief Complete semantic analysis for a reference to the given declaration.
-ExprResult
-Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- NamedDecl *D, NamedDecl *FoundD) {
+ExprResult Sema::BuildDeclarationNameExpr(
+ const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+ NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) {
assert(D && "Cannot refer to a NULL declaration");
assert(!isa<FunctionTemplateDecl>(D) &&
"Cannot refer unambiguously to a function template");
@@ -2492,8 +2622,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
// Specifically diagnose references to class templates that are missing
// a template argument list.
- Diag(Loc, diag::err_template_decl_ref)
- << Template << SS.getRange();
+ Diag(Loc, diag::err_template_decl_ref) << (isa<VarTemplateDecl>(D) ? 1 : 0)
+ << Template << SS.getRange();
Diag(Template->getLocation(), diag::note_template_decl_here);
return ExprError();
}
@@ -2583,6 +2713,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
}
case Decl::Var:
+ case Decl::VarTemplateSpecialization:
+ case Decl::VarTemplatePartialSpecialization:
// In C, "extern void blah;" is valid and is an r-value.
if (!getLangOpts().CPlusPlus &&
!type.hasQualifiers() &&
@@ -2680,32 +2812,23 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
break;
}
- return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD);
+ return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD,
+ TemplateArgs);
}
}
-ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
- PredefinedExpr::IdentType IT;
-
- switch (Kind) {
- default: llvm_unreachable("Unknown simple primary expr!");
- case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
- case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
- case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
- case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
- }
-
- // Pre-defined identifiers are of type char[x], where x is the length of the
- // string.
-
- Decl *currentDecl = getCurFunctionOrMethodDecl();
- // Blocks and lambdas can occur at global scope. Don't emit a warning.
- if (!currentDecl) {
- if (const BlockScopeInfo *BSI = getCurBlock())
- currentDecl = BSI->TheDecl;
- else if (const LambdaScopeInfo *LSI = getCurLambda())
- currentDecl = LSI->CallOperator;
- }
+ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentType IT) {
+ // Pick the current block, lambda, captured statement or function.
+ Decl *currentDecl = 0;
+ if (const BlockScopeInfo *BSI = getCurBlock())
+ currentDecl = BSI->TheDecl;
+ else if (const LambdaScopeInfo *LSI = getCurLambda())
+ currentDecl = LSI->CallOperator;
+ else if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion())
+ currentDecl = CSI->TheCapturedDecl;
+ else
+ currentDecl = getCurFunctionOrMethodDecl();
if (!currentDecl) {
Diag(Loc, diag::ext_predef_outside_function);
@@ -2713,21 +2836,39 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
}
QualType ResTy;
- if (cast<DeclContext>(currentDecl)->isDependentContext()) {
+ if (cast<DeclContext>(currentDecl)->isDependentContext())
ResTy = Context.DependentTy;
- } else {
+ else {
+ // Pre-defined identifiers are of type char[x], where x is the length of
+ // the string.
unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
if (IT == PredefinedExpr::LFunction)
- ResTy = Context.WCharTy.withConst();
+ ResTy = Context.WideCharTy.withConst();
else
ResTy = Context.CharTy.withConst();
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
}
+
return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
}
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
+ PredefinedExpr::IdentType IT;
+
+ switch (Kind) {
+ default: llvm_unreachable("Unknown simple primary expr!");
+ case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
+ case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
+ case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
+ case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
+ case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
+ }
+
+ return BuildPredefinedExpr(Loc, IT);
+}
+
ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
SmallString<16> CharBuffer;
bool Invalid = false;
@@ -2742,7 +2883,7 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
QualType Ty;
if (Literal.isWide())
- Ty = Context.WCharTy; // L'x' -> wchar_t in C and C++.
+ Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++.
else if (Literal.isUTF16())
Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11.
else if (Literal.isUTF32())
@@ -2872,11 +3013,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
+ SourceLocation TokLoc = Tok.getLocation();
+
// Perform literal operator lookup to determine if we're building a raw
// literal or a cooked one.
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, CookedTy,
- /*AllowRawAndTemplate*/true)) {
+ /*AllowRaw*/true, /*AllowTemplate*/true,
+ /*AllowStringTemplate*/false)) {
case LOLR_Error:
return ExprError();
@@ -2887,19 +3031,17 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
} else {
llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0);
if (Literal.GetIntegerValue(ResultVal))
- Diag(Tok.getLocation(), diag::warn_integer_too_large);
+ Diag(Tok.getLocation(), diag::err_integer_too_large);
Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy,
Tok.getLocation());
}
- return BuildLiteralOperatorCall(R, OpNameInfo, Lit,
- Tok.getLocation());
+ return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc);
}
case LOLR_Raw: {
// C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the
// literal is treated as a call of the form
// operator "" X ("n")
- SourceLocation TokLoc = Tok.getLocation();
unsigned Length = Literal.getUDSuffixOffset();
QualType StrTy = Context.getConstantArrayType(
Context.CharTy.withConst(), llvm::APInt(32, Length + 1),
@@ -2910,7 +3052,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc);
}
- case LOLR_Template:
+ case LOLR_Template: {
// C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator
// template), L is treated as a call fo the form
// operator "" X <'c1', 'c2', ... 'ck'>()
@@ -2925,11 +3067,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
TemplateArgumentLocInfo ArgInfo;
ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
}
- return BuildLiteralOperatorCall(R, OpNameInfo, None, Tok.getLocation(),
+ return BuildLiteralOperatorCall(R, OpNameInfo, None, TokLoc,
&ExplicitArgs);
}
-
- llvm_unreachable("unexpected literal operator lookup result");
+ case LOLR_StringTemplate:
+ llvm_unreachable("unexpected literal operator lookup result");
+ }
}
Expr *Res;
@@ -2980,8 +3123,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
llvm::APInt ResultVal(MaxWidth, 0);
if (Literal.GetIntegerValue(ResultVal)) {
- // If this value didn't fit into uintmax_t, warn and force to ull.
- Diag(Tok.getLocation(), diag::warn_integer_too_large);
+ // If this value didn't fit into uintmax_t, error and force to ull.
+ Diag(Tok.getLocation(), diag::err_integer_too_large);
Ty = Context.UnsignedLongLongTy;
assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
"long long is not intmax_t?");
@@ -3103,6 +3246,10 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
SourceLocation Loc,
SourceRange ArgRange,
UnaryExprOrTypeTrait TraitKind) {
+ // Invalid types must be hard errors for SFINAE in C++.
+ if (S.LangOpts.CPlusPlus)
+ return true;
+
// C99 6.5.3.4p1:
if (T->isFunctionType() &&
(TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) {
@@ -3185,6 +3332,12 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
ExprTy = E->getType();
assert(!ExprTy->isReferenceType());
+ if (ExprTy->isFunctionType()) {
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_function_type)
+ << ExprKind << E->getSourceRange();
+ return true;
+ }
+
if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
E->getSourceRange(), ExprKind))
return true;
@@ -3258,6 +3411,12 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
ExprKind, ExprRange))
return true;
+ if (ExprType->isFunctionType()) {
+ Diag(OpLoc, diag::err_sizeof_alignof_function_type)
+ << ExprKind << ExprRange;
+ return true;
+ }
+
if (CheckObjCTraitOperandConstraints(*this, ExprType, OpLoc, ExprRange,
ExprKind))
return true;
@@ -3487,7 +3646,8 @@ static bool checkArithmeticOnObjCPointer(Sema &S,
SourceLocation opLoc,
Expr *op) {
assert(op->getType()->isObjCObjectPointerType());
- if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic())
+ if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic() &&
+ !S.LangOpts.ObjCSubscriptingLegacyRuntime)
return false;
S.Diag(opLoc, diag::err_arithmetic_nonfragile_interface)
@@ -3592,15 +3752,10 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// Use custom logic if this should be the pseudo-object subscript
// expression.
- if (!LangOpts.ObjCRuntime.isSubscriptPointerArithmetic())
+ if (!LangOpts.isSubscriptPointerArithmetic())
return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
ResultType = PTy->getPointeeType();
- if (!LangOpts.ObjCRuntime.allowsPointerArithmetic()) {
- Diag(LLoc, diag::err_subscript_nonfragile_interface)
- << ResultType << BaseExpr->getSourceRange();
- return ExprError();
- }
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
// Handle the uncommon case of "123[Ptr]".
BaseExpr = RHSExp;
@@ -3612,7 +3767,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = PTy->getPointeeType();
- if (!LangOpts.ObjCRuntime.allowsPointerArithmetic()) {
+ if (!LangOpts.isSubscriptPointerArithmetic()) {
Diag(LLoc, diag::err_subscript_nonfragile_interface)
<< ResultType << BaseExpr->getSourceRange();
return ExprError();
@@ -3720,7 +3875,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
InstantiatingTemplate Inst(*this, CallLoc, Param,
MutiLevelArgList.getInnermost());
- if (Inst)
+ if (Inst.isInvalid())
return ExprError();
ExprResult Result;
@@ -3795,12 +3950,71 @@ Sema::getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto,
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
if (Method->isInstance())
return VariadicMethod;
- }
+ } else if (Fn && Fn->getType() == Context.BoundMemberTy)
+ return VariadicMethod;
return VariadicFunction;
}
return VariadicDoesNotApply;
}
+namespace {
+class FunctionCallCCC : public FunctionCallFilterCCC {
+public:
+ FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName,
+ unsigned NumArgs, bool HasExplicitTemplateArgs)
+ : FunctionCallFilterCCC(SemaRef, NumArgs, HasExplicitTemplateArgs),
+ FunctionName(FuncName) {}
+
+ virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ if (!candidate.getCorrectionSpecifier() ||
+ candidate.getCorrectionAsIdentifierInfo() != FunctionName) {
+ return false;
+ }
+
+ return FunctionCallFilterCCC::ValidateCandidate(candidate);
+ }
+
+private:
+ const IdentifierInfo *const FunctionName;
+};
+}
+
+static TypoCorrection TryTypoCorrectionForCall(Sema &S,
+ DeclarationNameInfo FuncName,
+ ArrayRef<Expr *> Args) {
+ FunctionCallCCC CCC(S, FuncName.getName().getAsIdentifierInfo(),
+ Args.size(), false);
+ if (TypoCorrection Corrected =
+ S.CorrectTypo(FuncName, Sema::LookupOrdinaryName,
+ S.getScopeForContext(S.CurContext), NULL, CCC)) {
+ if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+ if (Corrected.isOverloaded()) {
+ OverloadCandidateSet OCS(FuncName.getLoc());
+ OverloadCandidateSet::iterator Best;
+ for (TypoCorrection::decl_iterator CD = Corrected.begin(),
+ CDEnd = Corrected.end();
+ CD != CDEnd; ++CD) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+ S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
+ OCS);
+ }
+ switch (OCS.BestViableFunction(S, FuncName.getLoc(), Best)) {
+ case OR_Success:
+ ND = Best->Function;
+ Corrected.setCorrectionDecl(ND);
+ break;
+ default:
+ break;
+ }
+ }
+ if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+ return Corrected;
+ }
+ }
+ }
+ return TypoCorrection();
+}
+
/// ConvertArgumentsForCall - Converts the arguments specified in
/// Args/NumArgs to the parameter types of the function FDecl with
/// function prototype Proto. Call is the call expression itself, and
@@ -3811,7 +4025,7 @@ bool
Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
bool IsExecConfig) {
// Bail out early if calling a builtin with custom typechecking.
@@ -3833,9 +4047,23 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// If too few arguments are available (and we don't have default
// arguments for the remaining parameters), don't make the call.
- if (NumArgs < NumArgsInProto) {
- if (NumArgs < MinArgs) {
- if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
+ if (Args.size() < NumArgsInProto) {
+ if (Args.size() < MinArgs) {
+ MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
+ TypoCorrection TC;
+ if (FDecl && (TC = TryTypoCorrectionForCall(
+ *this, DeclarationNameInfo(FDecl->getDeclName(),
+ (ME ? ME->getMemberLoc()
+ : Fn->getLocStart())),
+ Args))) {
+ unsigned diag_id =
+ MinArgs == NumArgsInProto && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_few_args_suggest
+ : diag::err_typecheck_call_too_few_args_at_least_suggest;
+ diagnoseTypo(TC, PDiag(diag_id) << FnKind << MinArgs
+ << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange());
+ } else if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
Diag(RParenLoc, MinArgs == NumArgsInProto && !Proto->isVariadic()
? diag::err_typecheck_call_too_few_args_one
: diag::err_typecheck_call_too_few_args_at_least_one)
@@ -3846,10 +4074,11 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
? diag::err_typecheck_call_too_few_args
: diag::err_typecheck_call_too_few_args_at_least)
<< FnKind
- << MinArgs << NumArgs << Fn->getSourceRange();
+ << MinArgs << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange();
// Emit the location of the prototype.
- if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
+ if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getLocStart(), diag::note_callee_decl)
<< FDecl;
@@ -3860,29 +4089,44 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// If too many are passed and not variadic, error on the extras and drop
// them.
- if (NumArgs > NumArgsInProto) {
+ if (Args.size() > NumArgsInProto) {
if (!Proto->isVariadic()) {
- if (NumArgsInProto == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
+ TypoCorrection TC;
+ if (FDecl && (TC = TryTypoCorrectionForCall(
+ *this, DeclarationNameInfo(FDecl->getDeclName(),
+ Fn->getLocStart()),
+ Args))) {
+ unsigned diag_id =
+ MinArgs == NumArgsInProto && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_many_args_suggest
+ : diag::err_typecheck_call_too_many_args_at_most_suggest;
+ diagnoseTypo(TC, PDiag(diag_id) << FnKind << NumArgsInProto
+ << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange());
+ } else if (NumArgsInProto == 1 && FDecl &&
+ FDecl->getParamDecl(0)->getDeclName())
Diag(Args[NumArgsInProto]->getLocStart(),
MinArgs == NumArgsInProto
? diag::err_typecheck_call_too_many_args_one
: diag::err_typecheck_call_too_many_args_at_most_one)
<< FnKind
- << FDecl->getParamDecl(0) << NumArgs << Fn->getSourceRange()
+ << FDecl->getParamDecl(0) << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange()
<< SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args[NumArgs-1]->getLocEnd());
+ Args.back()->getLocEnd());
else
Diag(Args[NumArgsInProto]->getLocStart(),
MinArgs == NumArgsInProto
? diag::err_typecheck_call_too_many_args
: diag::err_typecheck_call_too_many_args_at_most)
<< FnKind
- << NumArgsInProto << NumArgs << Fn->getSourceRange()
+ << NumArgsInProto << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange()
<< SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args[NumArgs-1]->getLocEnd());
+ Args.back()->getLocEnd());
// Emit the location of the prototype.
- if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
+ if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getLocStart(), diag::note_callee_decl)
<< FDecl;
@@ -3895,7 +4139,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn);
Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl,
- Proto, 0, Args, NumArgs, AllArgs, CallType);
+ Proto, 0, Args, AllArgs, CallType);
if (Invalid)
return true;
unsigned TotalNumArgs = AllArgs.size();
@@ -3909,15 +4153,15 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
unsigned FirstProtoArg,
- Expr **Args, unsigned NumArgs,
- SmallVector<Expr *, 8> &AllArgs,
+ ArrayRef<Expr *> Args,
+ SmallVectorImpl<Expr *> &AllArgs,
VariadicCallType CallType,
bool AllowExplicit,
bool IsListInitialization) {
unsigned NumArgsInProto = Proto->getNumArgs();
- unsigned NumArgsToCheck = NumArgs;
+ unsigned NumArgsToCheck = Args.size();
bool Invalid = false;
- if (NumArgs != NumArgsInProto)
+ if (Args.size() != NumArgsInProto)
// Use default arguments for missing arguments
NumArgsToCheck = NumArgsInProto;
unsigned ArgIx = 0;
@@ -3927,7 +4171,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
Expr *Arg;
ParmVarDecl *Param;
- if (ArgIx < NumArgs) {
+ if (ArgIx < Args.size()) {
Arg = Args[ArgIx++];
if (RequireCompleteType(Arg->getLocStart(),
@@ -3941,15 +4185,25 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
Param = FDecl->getParamDecl(i);
// Strip the unbridged-cast placeholder expression off, if applicable.
+ bool CFAudited = false;
if (Arg->getType() == Context.ARCUnbridgedCastTy &&
FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
(!Param || !Param->hasAttr<CFConsumedAttr>()))
Arg = stripARCUnbridgedCast(Arg);
+ else if (getLangOpts().ObjCAutoRefCount &&
+ FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
+ (!Param || !Param->hasAttr<CFConsumedAttr>()))
+ CFAudited = true;
InitializedEntity Entity = Param ?
InitializedEntity::InitializeParameter(Context, Param, ProtoArgType)
: InitializedEntity::InitializeParameter(Context, ProtoArgType,
Proto->isArgConsumed(i));
+
+ // Remember that parameter belongs to a CF audited API.
+ if (CFAudited)
+ Entity.setParameterCFAudited();
+
ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(Arg),
@@ -3988,7 +4242,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
// return __unknown_anytype aren't *really* variadic.
if (Proto->getResultType() == Context.UnknownAnyTy &&
FDecl && FDecl->isExternC()) {
- for (unsigned i = ArgIx; i != NumArgs; ++i) {
+ for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
QualType paramType; // ignored
ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType);
Invalid |= arg.isInvalid();
@@ -3997,7 +4251,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
// Otherwise do argument promotion, (C99 6.5.2.2p7).
} else {
- for (unsigned i = ArgIx; i != NumArgs; ++i) {
+ for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType,
FDecl);
Invalid |= Arg.isInvalid();
@@ -4006,7 +4260,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
}
// Check for array bounds violations.
- for (unsigned i = ArgIx; i != NumArgs; ++i)
+ for (unsigned i = ArgIx, e = Args.size(); i != e; ++i)
CheckArrayAccess(Args[i]);
}
return Invalid;
@@ -4014,6 +4268,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc();
+ if (DecayedTypeLoc DTL = TL.getAs<DecayedTypeLoc>())
+ TL = DTL.getOriginalLoc();
if (ArrayTypeLoc ATL = TL.getAs<ArrayTypeLoc>())
S.Diag(PVD->getLocation(), diag::note_callee_static_array)
<< ATL.getLocalSourceRange();
@@ -4188,8 +4444,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// Determine whether this is a call to an object (C++ [over.call.object]).
if (Fn->getType()->isRecordType())
return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc,
- ArgExprs.data(),
- ArgExprs.size(), RParenLoc));
+ ArgExprs, RParenLoc));
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
@@ -4198,8 +4453,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
}
if (Fn->getType() == Context.BoundMemberTy) {
- return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs.data(),
- ArgExprs.size(), RParenLoc);
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc);
}
}
@@ -4212,11 +4466,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
OverloadExpr *ovl = find.Expression;
if (isa<UnresolvedLookupExpr>(ovl)) {
UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
- return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs.data(),
- ArgExprs.size(), RParenLoc, ExecConfig);
+ return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs,
+ RParenLoc, ExecConfig);
} else {
- return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs.data(),
- ArgExprs.size(), RParenLoc);
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs,
+ RParenLoc);
}
}
}
@@ -4240,9 +4494,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
else if (isa<MemberExpr>(NakedFn))
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
- return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs.data(),
- ArgExprs.size(), RParenLoc, ExecConfig,
- IsExecConfig);
+ return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
+ ExecConfig, IsExecConfig);
}
ExprResult
@@ -4283,6 +4536,19 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
RParenLoc));
}
+/// ActOnConvertVectorExpr - create a new convert-vector expression from the
+/// provided arguments.
+///
+/// __builtin_convertvector( value, dst type )
+///
+ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc) {
+ TypeSourceInfo *TInfo;
+ GetTypeFromParser(ParsedDestTy, &TInfo);
+ return SemaConvertVectorExpr(E, TInfo, BuiltinLoc, RParenLoc);
+}
+
/// BuildResolvedCallExpr - Build a call to a resolved expression,
/// i.e. an expression not of \p OverloadTy. The expression should
/// unary-convert to an expression of function-pointer or
@@ -4292,7 +4558,7 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
ExprResult
Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
Expr *Config, bool IsExecConfig) {
FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
@@ -4318,17 +4584,12 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
CallExpr *TheCall;
if (Config)
TheCall = new (Context) CUDAKernelCallExpr(Context, Fn,
- cast<CallExpr>(Config),
- llvm::makeArrayRef(Args,NumArgs),
- Context.BoolTy,
- VK_RValue,
+ cast<CallExpr>(Config), Args,
+ Context.BoolTy, VK_RValue,
RParenLoc);
else
- TheCall = new (Context) CallExpr(Context, Fn,
- llvm::makeArrayRef(Args, NumArgs),
- Context.BoolTy,
- VK_RValue,
- RParenLoc);
+ TheCall = new (Context) CallExpr(Context, Fn, Args, Context.BoolTy,
+ VK_RValue, RParenLoc);
// Bail out early if calling a builtin with custom typechecking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
@@ -4391,8 +4652,8 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT);
if (Proto) {
- if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
- RParenLoc, IsExecConfig))
+ if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc,
+ IsExecConfig))
return ExprError();
} else {
assert(isa<FunctionNoProtoType>(FuncT) && "Unknown FunctionType!");
@@ -4401,11 +4662,11 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// Check if we have too few/too many template arguments, based
// on our knowledge of the function definition.
const FunctionDecl *Def = 0;
- if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
+ if (FDecl->hasBody(Def) && Args.size() != Def->param_size()) {
Proto = Def->getType()->getAs<FunctionProtoType>();
- if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size()))
+ if (!Proto || !(Proto->isVariadic() && Args.size() >= Def->param_size()))
Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
- << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
+ << (Args.size() > Def->param_size()) << FDecl << Fn->getSourceRange();
}
// If the function we're calling isn't a function prototype, but we have
@@ -4415,7 +4676,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
}
// Promote the arguments (C99 6.5.2.2p6).
- for (unsigned i = 0; i != NumArgs; i++) {
+ for (unsigned i = 0, e = Args.size(); i != e; i++) {
Expr *Arg = Args[i];
if (Proto && i < Proto->getNumArgs()) {
@@ -4456,7 +4717,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// Check for sentinels
if (NDecl)
- DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs);
+ DiagnoseSentinelCalls(NDecl, LParenLoc, Args);
// Do special checking on direct calls to functions.
if (FDecl) {
@@ -4466,7 +4727,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (BuiltinID)
return CheckBuiltinFunctionCall(BuiltinID, TheCall);
} else if (NDecl) {
- if (CheckBlockCall(NDecl, TheCall, Proto))
+ if (CheckPointerCall(NDecl, TheCall, Proto))
+ return ExprError();
+ } else {
+ if (CheckOtherCall(TheCall, Proto))
return ExprError();
}
@@ -4476,7 +4740,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
ExprResult
Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
SourceLocation RParenLoc, Expr *InitExpr) {
- assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
+ assert(Ty && "ActOnCompoundLiteral(): missing type");
// FIXME: put back this assert when initializers are worked out.
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
@@ -4522,7 +4786,10 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
LiteralExpr = Result.get();
bool isFileScope = getCurFunctionOrMethodDecl() == 0;
- if (isFileScope) { // 6.5.2.5p3
+ if (isFileScope &&
+ !LiteralExpr->isTypeDependent() &&
+ !LiteralExpr->isValueDependent() &&
+ !literalType->isDependentType()) { // 6.5.2.5p3
if (CheckForConstantInitializer(LiteralExpr, literalType))
return ExprError();
}
@@ -5108,9 +5375,11 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
QualType lhptee, rhptee;
// Get the pointee types.
+ bool IsBlockPointer = false;
if (const BlockPointerType *LHSBTy = LHSTy->getAs<BlockPointerType>()) {
lhptee = LHSBTy->getPointeeType();
rhptee = RHSTy->castAs<BlockPointerType>()->getPointeeType();
+ IsBlockPointer = true;
} else {
lhptee = LHSTy->castAs<PointerType>()->getPointeeType();
rhptee = RHSTy->castAs<PointerType>()->getPointeeType();
@@ -5152,7 +5421,10 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
// The pointer types are compatible.
QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual);
- ResultTy = S.Context.getPointerType(ResultTy);
+ if (IsBlockPointer)
+ ResultTy = S.Context.getBlockPointerType(ResultTy);
+ else
+ ResultTy = S.Context.getPointerType(ResultTy);
LHS = S.ImpCastExprToType(LHS.take(), ResultTy, CK_BitCast);
RHS = S.ImpCastExprToType(RHS.take(), ResultTy, CK_BitCast);
@@ -5266,28 +5538,26 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
VK = VK_RValue;
OK = OK_Ordinary;
+ // First, check the condition.
Cond = UsualUnaryConversions(Cond.take());
if (Cond.isInvalid())
return QualType();
- LHS = UsualUnaryConversions(LHS.take());
- if (LHS.isInvalid())
+ if (checkCondition(*this, Cond.get()))
return QualType();
- RHS = UsualUnaryConversions(RHS.take());
- if (RHS.isInvalid())
+
+ // Now check the two expressions.
+ if (LHS.get()->getType()->isVectorType() ||
+ RHS.get()->getType()->isVectorType())
+ return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
+
+ UsualArithmeticConversions(LHS, RHS);
+ if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
QualType CondTy = Cond.get()->getType();
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
- // first, check the condition.
- if (checkCondition(*this, Cond.get()))
- return QualType();
-
- // Now check the two expressions.
- if (LHSTy->isVectorType() || RHSTy->isVectorType())
- return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
-
// If the condition is a vector, and both operands are scalar,
// attempt to implicity convert them to the vector type to act like the
// built in select. (OpenCL v1.1 s6.3.i)
@@ -5297,12 +5567,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
- if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
- UsualArithmeticConversions(LHS, RHS);
- if (LHS.isInvalid() || RHS.isInvalid())
- return QualType();
+ if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType())
return LHS.get()->getType();
- }
// If both operands are the same structure or union type, the result is that
// type.
@@ -5638,7 +5904,14 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
Expr *commonExpr = 0;
if (LHSExpr == 0) {
commonExpr = CondExpr;
-
+ // Lower out placeholder types first. This is important so that we don't
+ // try to capture a placeholder. This happens in few cases in C++; such
+ // as Objective-C++'s dictionary subscripting syntax.
+ if (commonExpr->hasPlaceholderType()) {
+ ExprResult result = CheckPlaceholderExpr(commonExpr);
+ if (!result.isUsable()) return ExprError();
+ commonExpr = result.take();
+ }
// We usually want to apply unary conversions *before* saving, except
// in the special case of a C++ l-value conditional.
if (!(getLangOpts().CPlusPlus
@@ -6248,7 +6521,8 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
Sema::AssignConvertType
Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
- bool Diagnose) {
+ bool Diagnose,
+ bool DiagnoseCFAudited) {
if (getLangOpts().CPlusPlus) {
if (!LHSType->isRecordType() && !LHSType->isAtomicType()) {
// C++ 5.17p3: If the left operand is not of class type, the
@@ -6290,12 +6564,14 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// C99 6.5.16.1p1: the left operand is a pointer and the right is
// a null pointer constant.
- if ((LHSType->isPointerType() ||
- LHSType->isObjCObjectPointerType() ||
- LHSType->isBlockPointerType())
- && RHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull)) {
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_NullToPointer);
+ if ((LHSType->isPointerType() || LHSType->isObjCObjectPointerType() ||
+ LHSType->isBlockPointerType()) &&
+ RHS.get()->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ CastKind Kind;
+ CXXCastPath Path;
+ CheckPointerConversion(RHS.get(), LHSType, Kind, Path, false);
+ RHS = ImpCastExprToType(RHS.take(), LHSType, Kind, VK_RValue, &Path);
return Compatible;
}
@@ -6321,9 +6597,14 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// so that we can use references in built-in functions even in C.
// The getNonReferenceType() call makes sure that the resulting expression
// does not have reference type.
- if (result != Incompatible && RHS.get()->getType() != LHSType)
- RHS = ImpCastExprToType(RHS.take(),
- LHSType.getNonLValueExprType(Context), Kind);
+ if (result != Incompatible && RHS.get()->getType() != LHSType) {
+ QualType Ty = LHSType.getNonLValueExprType(Context);
+ Expr *E = RHS.take();
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion,
+ DiagnoseCFAudited);
+ RHS = ImpCastExprToType(E, Ty, Kind);
+ }
return result;
}
@@ -6402,12 +6683,19 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
return LHSType;
}
}
- if (EltTy->isRealFloatingType() && RHSType->isScalarType() &&
- RHSType->isRealFloatingType()) {
- int order = Context.getFloatingTypeOrder(EltTy, RHSType);
- if (order > 0)
- RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast);
- if (order >= 0) {
+ if (EltTy->isRealFloatingType() && RHSType->isScalarType()) {
+ if (RHSType->isRealFloatingType()) {
+ int order = Context.getFloatingTypeOrder(EltTy, RHSType);
+ if (order > 0)
+ RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast);
+ if (order >= 0) {
+ RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
+ if (swapped) std::swap(RHS, LHS);
+ return LHSType;
+ }
+ }
+ if (RHSType->isIntegralType(Context)) {
+ RHS = ImpCastExprToType(RHS.take(), EltTy, CK_IntegralToFloating);
RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
if (swapped) std::swap(RHS, LHS);
return LHSType;
@@ -6480,11 +6768,12 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
return InvalidOperands(Loc, LHS, RHS);
// Check for division by zero.
- if (IsDiv &&
- RHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_division_by_zero)
- << RHS.get()->getSourceRange());
+ llvm::APSInt RHSValue;
+ if (IsDiv && !RHS.get()->isValueDependent() &&
+ RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0)
+ DiagRuntimeBehavior(Loc, RHS.get(),
+ PDiag(diag::warn_division_by_zero)
+ << RHS.get()->getSourceRange());
return compType;
}
@@ -6509,10 +6798,12 @@ QualType Sema::CheckRemainderOperands(
return InvalidOperands(Loc, LHS, RHS);
// Check for remainder by zero.
- if (RHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_remainder_by_zero)
- << RHS.get()->getSourceRange());
+ llvm::APSInt RHSValue;
+ if (!RHS.get()->isValueDependent() &&
+ RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0)
+ DiagRuntimeBehavior(Loc, RHS.get(),
+ PDiag(diag::warn_remainder_by_zero)
+ << RHS.get()->getSourceRange());
return compType;
}
@@ -6685,12 +6976,63 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
// Only print a fixit for "str" + int, not for int + "str".
if (IndexExpr == RHSExpr) {
SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
- Self.Diag(OpLoc, diag::note_string_plus_int_silence)
+ Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
<< FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
<< FixItHint::CreateInsertion(EndLoc, "]");
} else
- Self.Diag(OpLoc, diag::note_string_plus_int_silence);
+ Self.Diag(OpLoc, diag::note_string_plus_scalar_silence);
+}
+
+/// \brief Emit a warning when adding a char literal to a string.
+static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
+ Expr *LHSExpr, Expr *RHSExpr) {
+ const DeclRefExpr *StringRefExpr =
+ dyn_cast<DeclRefExpr>(LHSExpr->IgnoreImpCasts());
+ const CharacterLiteral *CharExpr =
+ dyn_cast<CharacterLiteral>(RHSExpr->IgnoreImpCasts());
+ if (!StringRefExpr) {
+ StringRefExpr = dyn_cast<DeclRefExpr>(RHSExpr->IgnoreImpCasts());
+ CharExpr = dyn_cast<CharacterLiteral>(LHSExpr->IgnoreImpCasts());
+ }
+
+ if (!CharExpr || !StringRefExpr)
+ return;
+
+ const QualType StringType = StringRefExpr->getType();
+
+ // Return if not a PointerType.
+ if (!StringType->isAnyPointerType())
+ return;
+
+ // Return if not a CharacterType.
+ if (!StringType->getPointeeType()->isAnyCharacterType())
+ return;
+
+ ASTContext &Ctx = Self.getASTContext();
+ SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+
+ const QualType CharType = CharExpr->getType();
+ if (!CharType->isAnyCharacterType() &&
+ CharType->isIntegerType() &&
+ llvm::isUIntN(Ctx.getCharWidth(), CharExpr->getValue())) {
+ Self.Diag(OpLoc, diag::warn_string_plus_char)
+ << DiagRange << Ctx.CharTy;
+ } else {
+ Self.Diag(OpLoc, diag::warn_string_plus_char)
+ << DiagRange << CharExpr->getType();
+ }
+
+ // Only print a fixit for str + char, not for char + str.
+ if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) {
+ SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
+ Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
+ << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
+ << FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
+ << FixItHint::CreateInsertion(EndLoc, "]");
+ } else {
+ Self.Diag(OpLoc, diag::note_string_plus_scalar_silence);
+ }
}
/// \brief Emit error when two pointers are incompatible.
@@ -6719,9 +7061,11 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
- // Diagnose "string literal" '+' int.
- if (Opc == BO_Add)
+ // Diagnose "string literal" '+' int and string '+' "char literal".
+ if (Opc == BO_Add) {
diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get());
+ diagnoseStringPlusChar(*this, Loc, LHS.get(), RHS.get());
+ }
// handle the common case first (both operands are arithmetic).
if (!compType.isNull() && compType->isArithmeticType()) {
@@ -6846,6 +7190,18 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
LHS.get(), RHS.get()))
return QualType();
+ // The pointee type may have zero size. As an extension, a structure or
+ // union may have zero size or an array may have zero length. In this
+ // case subtraction does not make sense.
+ if (!rpointee->isVoidType() && !rpointee->isFunctionType()) {
+ CharUnits ElementSize = Context.getTypeSizeInChars(rpointee);
+ if (ElementSize.isZero()) {
+ Diag(Loc,diag::warn_sub_ptr_zero_size_types)
+ << rpointee.getUnqualifiedType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ }
+ }
+
if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
return Context.getPointerDiffType();
}
@@ -7234,6 +7590,65 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
}
}
+static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc,
+ unsigned OpaqueOpc) {
+ // This checking requires bools.
+ if (!S.getLangOpts().Bool) return;
+
+ // Check that left hand side is !something.
+ UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS.get()->IgnoreImpCasts());
+ if (!UO || UO->getOpcode() != UO_LNot) return;
+
+ // Only check if the right hand side is non-bool arithmetic type.
+ if (RHS.get()->getType()->isBooleanType()) return;
+
+ // Make sure that the something in !something is not bool.
+ Expr *SubExpr = UO->getSubExpr()->IgnoreImpCasts();
+ if (SubExpr->getType()->isBooleanType()) return;
+
+ // Emit warning.
+ S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_comparison)
+ << Loc;
+
+ // First note suggest !(x < y)
+ SourceLocation FirstOpen = SubExpr->getLocStart();
+ SourceLocation FirstClose = RHS.get()->getLocEnd();
+ FirstClose = S.getPreprocessor().getLocForEndOfToken(FirstClose);
+ if (FirstClose.isInvalid())
+ FirstOpen = SourceLocation();
+ S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix)
+ << FixItHint::CreateInsertion(FirstOpen, "(")
+ << FixItHint::CreateInsertion(FirstClose, ")");
+
+ // Second note suggests (!x) < y
+ SourceLocation SecondOpen = LHS.get()->getLocStart();
+ SourceLocation SecondClose = LHS.get()->getLocEnd();
+ SecondClose = S.getPreprocessor().getLocForEndOfToken(SecondClose);
+ if (SecondClose.isInvalid())
+ SecondOpen = SourceLocation();
+ S.Diag(UO->getOperatorLoc(), diag::note_logical_not_silence_with_parens)
+ << FixItHint::CreateInsertion(SecondOpen, "(")
+ << FixItHint::CreateInsertion(SecondClose, ")");
+}
+
+// Get the decl for a simple expression: a reference to a variable,
+// an implicit C++ field reference, or an implicit ObjC ivar reference.
+static ValueDecl *getCompareDecl(Expr *E) {
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
+ return DR->getDecl();
+ if (ObjCIvarRefExpr* Ivar = dyn_cast<ObjCIvarRefExpr>(E)) {
+ if (Ivar->isFreeIvar())
+ return Ivar->getDecl();
+ }
+ if (MemberExpr* Mem = dyn_cast<MemberExpr>(E)) {
+ if (Mem->isImplicitAccess())
+ return Mem->getMemberDecl();
+ }
+ return 0;
+}
+
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, unsigned OpaqueOpc,
@@ -7254,11 +7669,13 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts();
checkEnumComparison(*this, Loc, LHS.get(), RHS.get());
+ diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, OpaqueOpc);
if (!LHSType->hasFloatingRepresentation() &&
!(LHSType->isBlockPointerType() && IsRelational) &&
!LHS.get()->getLocStart().isMacroID() &&
- !RHS.get()->getLocStart().isMacroID()) {
+ !RHS.get()->getLocStart().isMacroID() &&
+ ActiveTemplateInstantiations.empty()) {
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
@@ -7269,37 +7686,34 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// obvious cases in the definition of the template anyways. The idea is to
// warn when the typed comparison operator will always evaluate to the same
// result.
- if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) {
- if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
- if (DRL->getDecl() == DRR->getDecl() &&
- !IsWithinTemplateSpecialization(DRL->getDecl())) {
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
- << 0 // self-
- << (Opc == BO_EQ
- || Opc == BO_LE
- || Opc == BO_GE));
- } else if (LHSType->isArrayType() && RHSType->isArrayType() &&
- !DRL->getDecl()->getType()->isReferenceType() &&
- !DRR->getDecl()->getType()->isReferenceType()) {
- // what is it always going to eval to?
- char always_evals_to;
- switch(Opc) {
- case BO_EQ: // e.g. array1 == array2
- always_evals_to = 0; // false
- break;
- case BO_NE: // e.g. array1 != array2
- always_evals_to = 1; // true
- break;
- default:
- // best we can say is 'a constant'
- always_evals_to = 2; // e.g. array1 <= array2
- break;
- }
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
- << 1 // array
- << always_evals_to);
+ ValueDecl *DL = getCompareDecl(LHSStripped);
+ ValueDecl *DR = getCompareDecl(RHSStripped);
+ if (DL && DR && DL == DR && !IsWithinTemplateSpecialization(DL)) {
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 0 // self-
+ << (Opc == BO_EQ
+ || Opc == BO_LE
+ || Opc == BO_GE));
+ } else if (DL && DR && LHSType->isArrayType() && RHSType->isArrayType() &&
+ !DL->getType()->isReferenceType() &&
+ !DR->getType()->isReferenceType()) {
+ // what is it always going to eval to?
+ char always_evals_to;
+ switch(Opc) {
+ case BO_EQ: // e.g. array1 == array2
+ always_evals_to = 0; // false
+ break;
+ case BO_NE: // e.g. array1 != array2
+ always_evals_to = 1; // true
+ break;
+ default:
+ // best we can say is 'a constant'
+ always_evals_to = 2; // e.g. array1 <= array2
+ break;
}
- }
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << always_evals_to);
}
if (isa<CastExpr>(LHSStripped))
@@ -7333,21 +7747,9 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
}
// C99 6.5.8p3 / C99 6.5.9p4
- if (LHS.get()->getType()->isArithmeticType() &&
- RHS.get()->getType()->isArithmeticType()) {
- UsualArithmeticConversions(LHS, RHS);
- if (LHS.isInvalid() || RHS.isInvalid())
- return QualType();
- }
- else {
- LHS = UsualUnaryConversions(LHS.take());
- if (LHS.isInvalid())
- return QualType();
-
- RHS = UsualUnaryConversions(RHS.take());
- if (RHS.isInvalid())
- return QualType();
- }
+ UsualArithmeticConversions(LHS, RHS);
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
LHSType = LHS.get()->getType();
RHSType = RHS.get()->getType();
@@ -7534,12 +7936,20 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
/*isError*/false);
}
- if (LHSIsNull && !RHSIsNull)
- LHS = ImpCastExprToType(LHS.take(), RHSType,
+ if (LHSIsNull && !RHSIsNull) {
+ Expr *E = LHS.take();
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckObjCARCConversion(SourceRange(), RHSType, E, CCK_ImplicitConversion);
+ LHS = ImpCastExprToType(E, RHSType,
RPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
- else
- RHS = ImpCastExprToType(RHS.take(), LHSType,
+ }
+ else {
+ Expr *E = RHS.take();
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckObjCARCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion);
+ RHS = ImpCastExprToType(E, LHSType,
LPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
+ }
return ResultTy;
}
if (LHSType->isObjCObjectPointerType() &&
@@ -7651,7 +8061,8 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
- if (!LHSType->hasFloatingRepresentation()) {
+ if (!LHSType->hasFloatingRepresentation() &&
+ ActiveTemplateInstantiations.empty()) {
if (DeclRefExpr* DRL
= dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts()))
if (DeclRefExpr* DRR
@@ -7806,28 +8217,6 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
return Context.BoolTy;
}
-/// IsReadonlyProperty - Verify that otherwise a valid l-value expression
-/// is a read-only property; return true if so. A readonly property expression
-/// depends on various declarations and thus must be treated specially.
-///
-static bool IsReadonlyProperty(Expr *E, Sema &S) {
- const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E);
- if (!PropExpr) return false;
- if (PropExpr->isImplicitProperty()) return false;
-
- ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
- QualType BaseType = PropExpr->isSuperReceiver() ?
- PropExpr->getSuperReceiverType() :
- PropExpr->getBase()->getType();
-
- if (const ObjCObjectPointerType *OPT =
- BaseType->getAsObjCInterfacePointerType())
- if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
- if (S.isPropertyReadonly(PDecl, IFace))
- return true;
- return false;
-}
-
static bool IsReadonlyMessage(Expr *E, Sema &S) {
const MemberExpr *ME = dyn_cast<MemberExpr>(E);
if (!ME) return false;
@@ -7858,9 +8247,14 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
// Decide whether the first capture was for a block or a lambda.
- DeclContext *DC = S.CurContext;
- while (DC->getParent() != var->getDeclContext())
+ DeclContext *DC = S.CurContext, *Prev = 0;
+ while (DC != var->getDeclContext()) {
+ Prev = DC;
DC = DC->getParent();
+ }
+ // Unless we have an init-capture, we've gone one step too far.
+ if (!var->isInitCapture())
+ DC = Prev;
return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
}
@@ -7871,9 +8265,7 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
SourceLocation OrigLoc = Loc;
Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
&Loc);
- if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
- IsLV = Expr::MLV_ReadonlyProperty;
- else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
+ if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
IsLV = Expr::MLV_InvalidMessageExpression;
if (IsLV == Expr::MLV_Valid)
return false;
@@ -7956,7 +8348,6 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_DuplicateVectorComponents:
Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
break;
- case Expr::MLV_ReadonlyProperty:
case Expr::MLV_NoSetterProperty:
llvm_unreachable("readonly properties should be processed differently");
case Expr::MLV_InvalidMessageExpression:
@@ -8163,6 +8554,10 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
}
// Increment of bool sets it to true, but is deprecated.
S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+ } else if (S.getLangOpts().CPlusPlus && ResType->isEnumeralType()) {
+ // Error on enum increments and decrements in C++ mode
+ S.Diag(OpLoc, diag::err_increment_decrement_enum) << IsInc << ResType;
+ return QualType();
} else if (ResType->isRealType()) {
// OK!
} else if (ResType->isPointerType()) {
@@ -8186,6 +8581,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
IsInc, IsPrefix);
} else if (S.getLangOpts().AltiVec && ResType->isVectorType()) {
// OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
+ } else if(S.getLangOpts().OpenCL && ResType->isVectorType() &&
+ ResType->getAs<VectorType>()->getElementType()->isIntegerType()) {
+ // OpenCL V1.2 6.3 says dec/inc ops operate on integer vector types.
} else {
S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
<< ResType << int(IsInc) << Op->getSourceRange();
@@ -8289,43 +8687,50 @@ static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
/// In C++, the operand might be an overloaded function name, in which case
/// we allow the '&' but retain the overloaded-function type.
-static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
- SourceLocation OpLoc) {
+QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
if (PTy->getKind() == BuiltinType::Overload) {
- if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) {
- assert(cast<UnaryOperator>(OrigOp.get()->IgnoreParens())->getOpcode()
- == UO_AddrOf);
- S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function)
+ Expr *E = OrigOp.get()->IgnoreParens();
+ if (!isa<OverloadExpr>(E)) {
+ assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
+ Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
-
- return S.Context.OverloadTy;
+
+ OverloadExpr *Ovl = cast<OverloadExpr>(E);
+ if (isa<UnresolvedMemberExpr>(Ovl))
+ if (!ResolveSingleFunctionTemplateSpecialization(Ovl)) {
+ Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ << OrigOp.get()->getSourceRange();
+ return QualType();
+ }
+
+ return Context.OverloadTy;
}
if (PTy->getKind() == BuiltinType::UnknownAny)
- return S.Context.UnknownAnyTy;
+ return Context.UnknownAnyTy;
if (PTy->getKind() == BuiltinType::BoundMember) {
- S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
- OrigOp = S.CheckPlaceholderExpr(OrigOp.take());
+ OrigOp = CheckPlaceholderExpr(OrigOp.take());
if (OrigOp.isInvalid()) return QualType();
}
if (OrigOp.get()->isTypeDependent())
- return S.Context.DependentTy;
+ return Context.DependentTy;
assert(!OrigOp.get()->getType()->isPlaceholderType());
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp.get()->IgnoreParens();
- if (S.getLangOpts().C99) {
+ if (getLangOpts().C99) {
// Implement C99-only parts of addressof rules.
if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
if (uOp->getOpcode() == UO_Deref)
@@ -8337,28 +8742,28 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
// expressions here, but the result of one is always an lvalue anyway.
}
ValueDecl *dcl = getPrimaryDecl(op);
- Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
+ Expr::LValueClassification lval = op->ClassifyLValue(Context);
unsigned AddressOfError = AO_No_Error;
if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
- bool sfinae = (bool)S.isSFINAEContext();
- S.Diag(OpLoc, S.isSFINAEContext() ? diag::err_typecheck_addrof_temporary
- : diag::ext_typecheck_addrof_temporary)
+ bool sfinae = (bool)isSFINAEContext();
+ Diag(OpLoc, isSFINAEContext() ? diag::err_typecheck_addrof_temporary
+ : diag::ext_typecheck_addrof_temporary)
<< op->getType() << op->getSourceRange();
if (sfinae)
return QualType();
// Materialize the temporary as an lvalue so that we can take its address.
- OrigOp = op = new (S.Context)
- MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true);
+ OrigOp = op = new (Context)
+ MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true, 0);
} else if (isa<ObjCSelectorExpr>(op)) {
- return S.Context.getPointerType(op->getType());
+ return Context.getPointerType(op->getType());
} else if (lval == Expr::LV_MemberFunction) {
// If it's an instance method, make a member pointer.
// The expression must have exactly the form &A::foo.
// If the underlying expression isn't a decl ref, give up.
if (!isa<DeclRefExpr>(op)) {
- S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
@@ -8367,25 +8772,29 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
// The id-expression was parenthesized.
if (OrigOp.get() != DRE) {
- S.Diag(OpLoc, diag::err_parens_pointer_member_function)
+ Diag(OpLoc, diag::err_parens_pointer_member_function)
<< OrigOp.get()->getSourceRange();
// The method was named without a qualifier.
} else if (!DRE->getQualifier()) {
if (MD->getParent()->getName().empty())
- S.Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+ Diag(OpLoc, diag::err_unqualified_pointer_member_function)
<< op->getSourceRange();
else {
SmallString<32> Str;
StringRef Qual = (MD->getParent()->getName() + "::").toStringRef(Str);
- S.Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+ Diag(OpLoc, diag::err_unqualified_pointer_member_function)
<< op->getSourceRange()
<< FixItHint::CreateInsertion(op->getSourceRange().getBegin(), Qual);
}
}
- return S.Context.getMemberPointerType(op->getType(),
- S.Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ // Taking the address of a dtor is illegal per C++ [class.dtor]p2.
+ if (isa<CXXDestructorDecl>(MD))
+ Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
+
+ return Context.getMemberPointerType(op->getType(),
+ Context.getTypeDeclType(MD->getParent()).getTypePtr());
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
// The operand must be either an l-value or a function designator
@@ -8394,7 +8803,7 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
if (isa<PseudoObjectExpr>(op)) {
AddressOfError = AO_Property_Expansion;
} else {
- S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
+ Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
<< op->getType() << op->getSourceRange();
return QualType();
}
@@ -8412,11 +8821,11 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
// in C++ it is not error to take address of a register
// variable (c++03 7.1.1P3)
if (vd->getStorageClass() == SC_Register &&
- !S.getLangOpts().CPlusPlus) {
+ !getLangOpts().CPlusPlus) {
AddressOfError = AO_Register_Variable;
}
} else if (isa<FunctionTemplateDecl>(dcl)) {
- return S.Context.OverloadTy;
+ return Context.OverloadTy;
} else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) {
// Okay: we can take the address of a field.
// Could be a pointer to member, though, if there is an explicit
@@ -8425,16 +8834,16 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (dcl->getType()->isReferenceType()) {
- S.Diag(OpLoc,
- diag::err_cannot_form_pointer_to_member_of_reference_type)
+ Diag(OpLoc,
+ diag::err_cannot_form_pointer_to_member_of_reference_type)
<< dcl->getDeclName() << dcl->getType();
return QualType();
}
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
Ctx = Ctx->getParent();
- return S.Context.getMemberPointerType(op->getType(),
- S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ return Context.getMemberPointerType(op->getType(),
+ Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
}
}
} else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
@@ -8442,7 +8851,7 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
}
if (AddressOfError != AO_No_Error) {
- diagnoseAddressOfInvalidType(S, OpLoc, op, AddressOfError);
+ diagnoseAddressOfInvalidType(*this, OpLoc, op, AddressOfError);
return QualType();
}
@@ -8450,13 +8859,13 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
// Taking the address of a void variable is technically illegal, but we
// allow it in cases which are otherwise valid.
// Example: "extern void x; void* y = &x;".
- S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
+ Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
}
// If the operand has type "type", the result has type "pointer to type".
if (op->getType()->isObjCObjectType())
- return S.Context.getObjCObjectPointerType(op->getType());
- return S.Context.getPointerType(op->getType());
+ return Context.getObjCObjectPointerType(op->getType());
+ return Context.getPointerType(op->getType());
}
/// CheckIndirectionOperand - Type check unary indirection (prefix '*').
@@ -8630,7 +9039,20 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
// looks for code trying to introspect into tagged pointers, which
// code should generally never do.
if (ObjCPointerExpr && isa<IntegerLiteral>(OtherExpr->IgnoreParenCasts())) {
- S.Diag(OpLoc, diag::warn_objc_pointer_masking)
+ unsigned Diag = diag::warn_objc_pointer_masking;
+ // Determine if we are introspecting the result of performSelectorXXX.
+ const Expr *Ex = ObjCPointerExpr->IgnoreParenCasts();
+ // Special case messages to -performSelector and friends, which
+ // can return non-pointer values boxed in a pointer value.
+ // Some clients may wish to silence warnings in this subcase.
+ if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(Ex)) {
+ Selector S = ME->getSelector();
+ StringRef SelArg0 = S.getNameForSlot(0);
+ if (SelArg0.startswith("performSelector"))
+ Diag = diag::warn_objc_pointer_masking_performSelector;
+ }
+
+ S.Diag(OpLoc, Diag)
<< ObjCPointerExpr->getSourceRange();
}
}
@@ -9149,7 +9571,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
Opc == UO_PreDec);
break;
case UO_AddrOf:
- resultType = CheckAddressOfOperand(*this, Input, OpLoc);
+ resultType = CheckAddressOfOperand(Input, OpLoc);
break;
case UO_Deref: {
Input = DefaultFunctionArrayLvalueConversion(Input.take());
@@ -9167,9 +9589,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
if (resultType->isArithmeticType() || // C99 6.5.3.3p1
resultType->isVectorType())
break;
- else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6-7
- resultType->isEnumeralType())
- break;
else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6
Opc == UO_Plus &&
resultType->isPointerType())
@@ -9392,7 +9811,7 @@ ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
LabelDecl *TheDecl) {
- TheDecl->setUsed();
+ TheDecl->markUsed(Context);
// Create the AST node. The address of a label always has type 'void*'.
return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
Context.getPointerType(Context.VoidTy)));
@@ -9657,9 +10076,15 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// If the member was found in a base class, introduce OffsetOfNodes for
// the base class indirections.
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
+ CXXBasePaths Paths;
if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
+ if (Paths.getDetectedVirtual()) {
+ Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base)
+ << MemberDecl->getDeclName()
+ << SourceRange(BuiltinLoc, RParenLoc);
+ return ExprError();
+ }
+
CXXBasePath &Path = Paths.front();
for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
B != BEnd; ++B)
@@ -9715,6 +10140,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
ExprObjectKind OK = OK_Ordinary;
QualType resType;
bool ValueDependent = false;
+ bool CondIsTrue = false;
if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
resType = Context.DependentTy;
ValueDependent = true;
@@ -9727,9 +10153,10 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
if (CondICE.isInvalid())
return ExprError();
CondExpr = CondICE.take();
+ CondIsTrue = condEval.getZExtValue();
// If the condition is > zero, then the AST type is the same as the LSHExpr.
- Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr;
+ Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr;
resType = ActiveExpr->getType();
ValueDependent = ActiveExpr->isValueDependent();
@@ -9738,7 +10165,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
}
return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
- resType, VK, OK, RPLoc,
+ resType, VK, OK, RPLoc, CondIsTrue,
resType->isDependentType(),
ValueDependent));
}
@@ -9750,6 +10177,17 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
/// ActOnBlockStart - This callback is invoked when a block literal is started.
void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
+
+ if (LangOpts.CPlusPlus) {
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ getCurrentMangleNumberContext(Block->getDeclContext(),
+ ManglingContextDecl)) {
+ unsigned ManglingNumber = MCtx->getManglingNumber(Block);
+ Block->setBlockMangling(ManglingNumber, ManglingContextDecl);
+ }
+ }
+
PushBlockScope(CurScope, Block);
CurContext->addDecl(Block);
if (CurScope)
@@ -9822,13 +10260,6 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
CurBlock->TheDecl->setIsVariadic(isVariadic);
- // Don't allow returning a objc interface by value.
- if (RetTy->isObjCObjectType()) {
- Diag(ParamInfo.getLocStart(),
- diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
- return;
- }
-
// Context.DependentTy is used as a placeholder for a missing block
// return type. TODO: what should we do with declarators like:
// ^ * { ... }
@@ -9876,11 +10307,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
// Finally we can process decl attributes.
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
- // Put the parameter variables in scope. We can bail out immediately
- // if we don't have any.
- if (Params.empty())
- return;
-
+ // Put the parameter variables in scope.
for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
(*AI)->setOwningFunction(CurBlock->TheDecl);
@@ -9942,7 +10369,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
- Cap.isNested(), Cap.getCopyExpr());
+ Cap.isNested(), Cap.getInitExpr());
Captures.push_back(NewCap);
}
BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(),
@@ -9973,11 +10400,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals = 0; // FIXME: silently?
EPI.ExtInfo = Ext;
- BlockTy =
- Context.getFunctionType(RetTy,
- ArrayRef<QualType>(FPT->arg_type_begin(),
- FPT->getNumArgs()),
- EPI);
+ BlockTy = Context.getFunctionType(RetTy, FPT->getArgTypes(), EPI);
}
// If we don't have a function type, just build one from nothing.
@@ -10007,7 +10430,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
computeNRVO(Body, getCurBlock());
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
- const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
+ AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
// If the block isn't obviously global, i.e. it captures anything at
@@ -10145,7 +10568,8 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
}
static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
- Expr *SrcExpr, FixItHint &Hint) {
+ Expr *SrcExpr, FixItHint &Hint,
+ bool &IsNSString) {
if (!SemaRef.getLangOpts().ObjC1)
return;
@@ -10159,6 +10583,7 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
if (!ID || !ID->getIdentifier()->isStr("NSString"))
return;
+ IsNSString = true;
}
// Ignore any parens, implicit casts (should only be
@@ -10192,6 +10617,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
ConversionFixItGenerator ConvHints;
bool MayHaveConvFixit = false;
bool MayHaveFunctionDiff = false;
+ bool IsNSString = false;
switch (ConvTy) {
case Compatible:
@@ -10209,8 +10635,11 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
MayHaveConvFixit = true;
break;
case IncompatiblePointer:
- MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint);
- DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
+ MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString);
+ DiagKind =
+ (Action == AA_Passing_CFAudited ?
+ diag::err_arc_typecheck_convert_incompatible_pointer :
+ diag::ext_typecheck_convert_incompatible_pointer);
CheckInferredResultType = DstType->isObjCObjectPointerType() &&
SrcType->isObjCObjectPointerType();
if (Hint.isNull() && !CheckInferredResultType) {
@@ -10220,6 +10649,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SrcType = SrcType.getUnqualifiedType();
DstType = DstType.getUnqualifiedType();
}
+ else if (IsNSString && !Hint.isNull())
+ DiagKind = diag::warn_missing_atsign_prefix;
MayHaveConvFixit = true;
break;
case IncompatiblePointerSign:
@@ -10302,6 +10733,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
case AA_Returning:
case AA_Passing:
+ case AA_Passing_CFAudited:
case AA_Converting:
case AA_Sending:
case AA_Casting:
@@ -10312,7 +10744,10 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
}
PartialDiagnostic FDiag = PDiag(DiagKind);
- FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
+ if (Action == AA_Passing_CFAudited)
+ FDiag << FirstType << SecondType << SrcExpr->getSourceRange();
+ else
+ FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
// If we can fix the conversion, suggest the FixIts.
assert(ConvHints.isNull() || Hint.isNull());
@@ -10394,112 +10829,52 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
// have a single non-explicit conversion function to an integral or
// unscoped enumeration type
ExprResult Converted;
- if (!Diagnoser.Suppress) {
- class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
- public:
- CXX11ConvertDiagnoser() : ICEConvertDiagnoser(false, true) { }
-
- virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_ice_not_integral) << T;
- }
-
- virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,
- SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
- }
-
- virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;
- }
-
- virtual DiagnosticBuilder noteExplicitConv(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
- << ConvTy->isEnumeralType() << ConvTy;
- }
-
- virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
- }
-
- virtual DiagnosticBuilder noteAmbiguous(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
- << ConvTy->isEnumeralType() << ConvTy;
- }
-
- virtual DiagnosticBuilder diagnoseConversion(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
- } ConvertDiagnoser;
+ class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
+ public:
+ CXX11ConvertDiagnoser(bool Silent)
+ : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
+ Silent, true) {}
+
+ virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) {
+ return S.Diag(Loc, diag::err_ice_not_integral) << T;
+ }
- Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E,
- ConvertDiagnoser,
- /*AllowScopedEnumerations*/ false);
- } else {
- // The caller wants to silently enquire whether this is an ICE. Don't
- // produce any diagnostics if it isn't.
- class SilentICEConvertDiagnoser : public ICEConvertDiagnoser {
- public:
- SilentICEConvertDiagnoser() : ICEConvertDiagnoser(true, true) { }
-
- virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,
- SourceLocation Loc,
- QualType T) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder noteExplicitConv(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder noteAmbiguous(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder diagnoseConversion(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
- } ConvertDiagnoser;
-
- Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E,
- ConvertDiagnoser, false);
- }
+ virtual SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) {
+ return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) {
+ return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
+ }
+
+ virtual SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ llvm_unreachable("conversion functions are permitted");
+ }
+ } ConvertDiagnoser(Diagnoser.Suppress);
+
+ Converted = PerformContextualImplicitConversion(DiagLoc, E,
+ ConvertDiagnoser);
if (Converted.isInvalid())
return Converted;
E = Converted.take();
@@ -10647,21 +11022,30 @@ void
Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
ReuseLambdaContextDecl_t,
bool IsDecltype) {
- Decl *LambdaContextDecl = ExprEvalContexts.back().LambdaContextDecl;
- PushExpressionEvaluationContext(NewContext, LambdaContextDecl, IsDecltype);
+ Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
+ PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
}
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
if (!Rec.Lambdas.empty()) {
- if (Rec.isUnevaluated()) {
- // C++11 [expr.prim.lambda]p2:
- // A lambda-expression shall not appear in an unevaluated operand
- // (Clause 5).
+ if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) {
+ unsigned D;
+ if (Rec.isUnevaluated()) {
+ // C++11 [expr.prim.lambda]p2:
+ // A lambda-expression shall not appear in an unevaluated operand
+ // (Clause 5).
+ D = diag::err_lambda_unevaluated_operand;
+ } else {
+ // C++1y [expr.const]p2:
+ // A conditional-expression e is a core constant expression unless the
+ // evaluation of e, following the rules of the abstract machine, would
+ // evaluate [...] a lambda-expression.
+ D = diag::err_lambda_in_constant_expression;
+ }
for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I)
- Diag(Rec.Lambdas[I]->getLocStart(),
- diag::err_lambda_unevaluated_operand);
+ Diag(Rec.Lambdas[I]->getLocStart(), D);
} else {
// Mark the capture expressions odr-used. This was deferred
// during lambda expression creation.
@@ -10874,7 +11258,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
if (!AlreadyInstantiated || Func->isConstexpr()) {
if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
- cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass())
+ cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() &&
+ ActiveTemplateInstantiations.size())
PendingLocalImplicitInstantiations.push_back(
std::make_pair(Func, PointOfInstantiation));
else if (Func->isConstexpr())
@@ -10908,14 +11293,14 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
}
- // Normally the must current decl is marked used while processing the use and
+ // Normally the most current decl is marked used while processing the use and
// any subsequent decls are marked used by decl merging. This fails with
// template instantiation since marking can happen at the end of the file
// and, because of the two phase lookup, this function is called with at
// decl in the middle of a decl chain. We loop to maintain the invariant
// that once a decl is used, all decls after it are also used.
for (FunctionDecl *F = Func->getMostRecentDecl();; F = F->getPreviousDecl()) {
- F->setUsed(true);
+ F->markUsed(Context);
if (F == Func)
break;
}
@@ -10967,36 +11352,251 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
// capture.
}
-/// \brief Capture the given variable in the captured region.
-static ExprResult captureInCapturedRegion(Sema &S, CapturedRegionScopeInfo *RSI,
- VarDecl *Var, QualType FieldType,
- QualType DeclRefType,
- SourceLocation Loc,
- bool RefersToEnclosingLocal) {
- // The current implemention assumes that all variables are captured
- // by references. Since there is no capture by copy, no expression evaluation
- // will be needed.
- //
- RecordDecl *RD = RSI->TheRecordDecl;
+
+static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var,
+ bool &SubCapturesAreNested,
+ QualType &CaptureType,
+ QualType &DeclRefType) {
+ // Check whether we've already captured it.
+ if (CSI->CaptureMap.count(Var)) {
+ // If we found a capture, any subcaptures are nested.
+ SubCapturesAreNested = true;
+
+ // Retrieve the capture type for this variable.
+ CaptureType = CSI->getCapture(Var).getCaptureType();
+
+ // Compute the type of an expression that refers to this variable.
+ DeclRefType = CaptureType.getNonReferenceType();
+
+ const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
+ if (Cap.isCopyCapture() &&
+ !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable))
+ DeclRefType.addConst();
+ return true;
+ }
+ return false;
+}
- FieldDecl *Field
- = FieldDecl::Create(S.Context, RD, Loc, Loc, 0, FieldType,
- S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
- 0, false, ICIS_NoInit);
- Field->setImplicit(true);
- Field->setAccess(AS_private);
- RD->addDecl(Field);
+// Only block literals, captured statements, and lambda expressions can
+// capture; other scopes don't work.
+static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var,
+ SourceLocation Loc,
+ const bool Diagnose, Sema &S) {
+ if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC))
+ return getLambdaAwareParentOfDeclContext(DC);
+ else {
+ if (Diagnose)
+ diagnoseUncapturableValueReference(S, Loc, Var, DC);
+ }
+ return 0;
+}
- Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal,
- DeclRefType, VK_LValue, Loc);
- Var->setReferenced(true);
- Var->setUsed(true);
+// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
+// certain types of variables (unnamed, variably modified types etc.)
+// so check for eligibility.
+static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
+ SourceLocation Loc,
+ const bool Diagnose, Sema &S) {
+
+ bool IsBlock = isa<BlockScopeInfo>(CSI);
+ bool IsLambda = isa<LambdaScopeInfo>(CSI);
+
+ // Lambdas are not allowed to capture unnamed variables
+ // (e.g. anonymous unions).
+ // FIXME: The C++11 rule don't actually state this explicitly, but I'm
+ // assuming that's the intent.
+ if (IsLambda && !Var->getDeclName()) {
+ if (Diagnose) {
+ S.Diag(Loc, diag::err_lambda_capture_anonymous_var);
+ S.Diag(Var->getLocation(), diag::note_declared_at);
+ }
+ return false;
+ }
+
+ // Prohibit variably-modified types; they're difficult to deal with.
+ if (Var->getType()->isVariablyModifiedType()) {
+ if (Diagnose) {
+ if (IsBlock)
+ S.Diag(Loc, diag::err_ref_vm_type);
+ else
+ S.Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName();
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+ // Prohibit structs with flexible array members too.
+ // We cannot capture what is in the tail end of the struct.
+ if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) {
+ if (VTTy->getDecl()->hasFlexibleArrayMember()) {
+ if (Diagnose) {
+ if (IsBlock)
+ S.Diag(Loc, diag::err_ref_flexarray_type);
+ else
+ S.Diag(Loc, diag::err_lambda_capture_flexarray_type)
+ << Var->getDeclName();
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+ }
+ const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
+ // Lambdas and captured statements are not allowed to capture __block
+ // variables; they don't support the expected semantics.
+ if (HasBlocksAttr && (IsLambda || isa<CapturedRegionScopeInfo>(CSI))) {
+ if (Diagnose) {
+ S.Diag(Loc, diag::err_capture_block_variable)
+ << Var->getDeclName() << !IsLambda;
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
- return Ref;
+ return true;
}
-/// \brief Capture the given variable in the given lambda expression.
-static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
+// Returns true if the capture by block was successful.
+static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
+ QualType &CaptureType,
+ QualType &DeclRefType,
+ const bool Nested,
+ Sema &S) {
+ Expr *CopyExpr = 0;
+ bool ByRef = false;
+
+ // Blocks are not allowed to capture arrays.
+ if (CaptureType->isArrayType()) {
+ if (BuildAndDiagnose) {
+ S.Diag(Loc, diag::err_ref_array_type);
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+
+ // Forbid the block-capture of autoreleasing variables.
+ if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
+ if (BuildAndDiagnose) {
+ S.Diag(Loc, diag::err_arc_autoreleasing_capture)
+ << /*block*/ 0;
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+ const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
+ if (HasBlocksAttr || CaptureType->isReferenceType()) {
+ // Block capture by reference does not change the capture or
+ // declaration reference types.
+ ByRef = true;
+ } else {
+ // Block capture by copy introduces 'const'.
+ CaptureType = CaptureType.getNonReferenceType().withConst();
+ DeclRefType = CaptureType;
+
+ if (S.getLangOpts().CPlusPlus && BuildAndDiagnose) {
+ if (const RecordType *Record = DeclRefType->getAs<RecordType>()) {
+ // The capture logic needs the destructor, so make sure we mark it.
+ // Usually this is unnecessary because most local variables have
+ // their destructors marked at declaration time, but parameters are
+ // an exception because it's technically only the call site that
+ // actually requires the destructor.
+ if (isa<ParmVarDecl>(Var))
+ S.FinalizeVarWithDestructor(Var, Record);
+
+ // Enter a new evaluation context to insulate the copy
+ // full-expression.
+ EnterExpressionEvaluationContext scope(S, S.PotentiallyEvaluated);
+
+ // According to the blocks spec, the capture of a variable from
+ // the stack requires a const copy constructor. This is not true
+ // of the copy/move done to move a __block variable to the heap.
+ Expr *DeclRef = new (S.Context) DeclRefExpr(Var, Nested,
+ DeclRefType.withConst(),
+ VK_LValue, Loc);
+
+ ExprResult Result
+ = S.PerformCopyInitialization(
+ InitializedEntity::InitializeBlock(Var->getLocation(),
+ CaptureType, false),
+ Loc, S.Owned(DeclRef));
+
+ // Build a full-expression copy expression if initialization
+ // succeeded and used a non-trivial constructor. Recover from
+ // errors by pretending that the copy isn't necessary.
+ if (!Result.isInvalid() &&
+ !cast<CXXConstructExpr>(Result.get())->getConstructor()
+ ->isTrivial()) {
+ Result = S.MaybeCreateExprWithCleanups(Result);
+ CopyExpr = Result.take();
+ }
+ }
+ }
+ }
+
+ // Actually capture the variable.
+ if (BuildAndDiagnose)
+ BSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc,
+ SourceLocation(), CaptureType, CopyExpr);
+
+ return true;
+
+}
+
+
+/// \brief Capture the given variable in the captured region.
+static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
+ VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
+ QualType &CaptureType,
+ QualType &DeclRefType,
+ const bool RefersToEnclosingLocal,
+ Sema &S) {
+
+ // By default, capture variables by reference.
+ bool ByRef = true;
+ // Using an LValue reference type is consistent with Lambdas (see below).
+ CaptureType = S.Context.getLValueReferenceType(DeclRefType);
+ Expr *CopyExpr = 0;
+ if (BuildAndDiagnose) {
+ // The current implementation assumes that all variables are captured
+ // by references. Since there is no capture by copy, no expression evaluation
+ // will be needed.
+ //
+ RecordDecl *RD = RSI->TheRecordDecl;
+
+ FieldDecl *Field
+ = FieldDecl::Create(S.Context, RD, Loc, Loc, 0, CaptureType,
+ S.Context.getTrivialTypeSourceInfo(CaptureType, Loc),
+ 0, false, ICIS_NoInit);
+ Field->setImplicit(true);
+ Field->setAccess(AS_private);
+ RD->addDecl(Field);
+
+ CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal,
+ DeclRefType, VK_LValue, Loc);
+ Var->setReferenced(true);
+ Var->markUsed(S.Context);
+ }
+
+ // Actually capture the variable.
+ if (BuildAndDiagnose)
+ RSI->addCapture(Var, /*isBlock*/false, ByRef, RefersToEnclosingLocal, Loc,
+ SourceLocation(), CaptureType, CopyExpr);
+
+
+ return true;
+}
+
+/// \brief Create a field within the lambda class for the variable
+/// being captured. Handle Array captures.
+static ExprResult addAsFieldToClosureType(Sema &S,
+ LambdaScopeInfo *LSI,
VarDecl *Var, QualType FieldType,
QualType DeclRefType,
SourceLocation Loc,
@@ -11032,7 +11632,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal,
DeclRefType, VK_LValue, Loc);
Var->setReferenced(true);
- Var->setUsed(true);
+ Var->markUsed(S.Context);
// When the field has array type, create index variables for each
// dimension of the array. We use these index variables to subscript
@@ -11088,7 +11688,8 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
SmallVector<InitializedEntity, 4> Entities;
Entities.reserve(1 + IndexVariables.size());
Entities.push_back(
- InitializedEntity::InitializeLambdaCapture(Var, Field, Loc));
+ InitializedEntity::InitializeLambdaCapture(Var->getIdentifier(),
+ Field->getType(), Loc));
for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
Entities.push_back(InitializedEntity::InitializeElement(S.Context,
0,
@@ -11113,127 +11714,207 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
return Result;
}
-bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
+
+
+/// \brief Capture the given variable in the lambda.
+static bool captureInLambda(LambdaScopeInfo *LSI,
+ VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
+ QualType &CaptureType,
+ QualType &DeclRefType,
+ const bool RefersToEnclosingLocal,
+ const Sema::TryCaptureKind Kind,
+ SourceLocation EllipsisLoc,
+ const bool IsTopScope,
+ Sema &S) {
+
+ // Determine whether we are capturing by reference or by value.
+ bool ByRef = false;
+ if (IsTopScope && Kind != Sema::TryCapture_Implicit) {
+ ByRef = (Kind == Sema::TryCapture_ExplicitByRef);
+ } else {
+ ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
+ }
+
+ // Compute the type of the field that will capture this variable.
+ if (ByRef) {
+ // C++11 [expr.prim.lambda]p15:
+ // An entity is captured by reference if it is implicitly or
+ // explicitly captured but not captured by copy. It is
+ // unspecified whether additional unnamed non-static data
+ // members are declared in the closure type for entities
+ // captured by reference.
+ //
+ // FIXME: It is not clear whether we want to build an lvalue reference
+ // to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears
+ // to do the former, while EDG does the latter. Core issue 1249 will
+ // clarify, but for now we follow GCC because it's a more permissive and
+ // easily defensible position.
+ CaptureType = S.Context.getLValueReferenceType(DeclRefType);
+ } else {
+ // C++11 [expr.prim.lambda]p14:
+ // For each entity captured by copy, an unnamed non-static
+ // data member is declared in the closure type. The
+ // declaration order of these members is unspecified. The type
+ // of such a data member is the type of the corresponding
+ // captured entity if the entity is not a reference to an
+ // object, or the referenced type otherwise. [Note: If the
+ // captured entity is a reference to a function, the
+ // corresponding data member is also a reference to a
+ // function. - end note ]
+ if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()){
+ if (!RefType->getPointeeType()->isFunctionType())
+ CaptureType = RefType->getPointeeType();
+ }
+
+ // Forbid the lambda copy-capture of autoreleasing variables.
+ if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
+ if (BuildAndDiagnose) {
+ S.Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1;
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+
+ if (S.RequireNonAbstractType(Loc, CaptureType,
+ diag::err_capture_of_abstract_type))
+ return false;
+ }
+
+ // Capture this variable in the lambda.
+ Expr *CopyExpr = 0;
+ if (BuildAndDiagnose) {
+ ExprResult Result = addAsFieldToClosureType(S, LSI, Var,
+ CaptureType, DeclRefType, Loc,
+ RefersToEnclosingLocal);
+ if (!Result.isInvalid())
+ CopyExpr = Result.take();
+ }
+
+ // Compute the type of a reference to this captured variable.
+ if (ByRef)
+ DeclRefType = CaptureType.getNonReferenceType();
+ else {
+ // C++ [expr.prim.lambda]p5:
+ // The closure type for a lambda-expression has a public inline
+ // function call operator [...]. This function call operator is
+ // declared const (9.3.1) if and only if the lambda-expression’s
+ // parameter-declaration-clause is not followed by mutable.
+ DeclRefType = CaptureType.getNonReferenceType();
+ if (!LSI->Mutable && !CaptureType->isReferenceType())
+ DeclRefType.addConst();
+ }
+
+ // Add the capture.
+ if (BuildAndDiagnose)
+ LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToEnclosingLocal,
+ Loc, EllipsisLoc, CaptureType, CopyExpr);
+
+ return true;
+}
+
+
+bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
TryCaptureKind Kind, SourceLocation EllipsisLoc,
bool BuildAndDiagnose,
QualType &CaptureType,
- QualType &DeclRefType) {
+ QualType &DeclRefType,
+ const unsigned *const FunctionScopeIndexToStopAt) {
bool Nested = false;
DeclContext *DC = CurContext;
- if (Var->getDeclContext() == DC) return true;
- if (!Var->hasLocalStorage()) return true;
+ const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
+ ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+ // We need to sync up the Declaration Context with the
+ // FunctionScopeIndexToStopAt
+ if (FunctionScopeIndexToStopAt) {
+ unsigned FSIndex = FunctionScopes.size() - 1;
+ while (FSIndex != MaxFunctionScopesIndex) {
+ DC = getLambdaAwareParentOfDeclContext(DC);
+ --FSIndex;
+ }
+ }
- bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
+
+ // If the variable is declared in the current context (and is not an
+ // init-capture), there is no need to capture it.
+ if (!Var->isInitCapture() && Var->getDeclContext() == DC) return true;
+ if (!Var->hasLocalStorage()) return true;
// Walk up the stack to determine whether we can capture the variable,
// performing the "simple" checks that don't depend on type. We stop when
// we've either hit the declared scope of the variable or find an existing
- // capture of that variable.
+ // capture of that variable. We start from the innermost capturing-entity
+ // (the DC) and ensure that all intervening capturing-entities
+ // (blocks/lambdas etc.) between the innermost capturer and the variable`s
+ // declcontext can either capture the variable or have already captured
+ // the variable.
CaptureType = Var->getType();
DeclRefType = CaptureType.getNonReferenceType();
bool Explicit = (Kind != TryCapture_Implicit);
- unsigned FunctionScopesIndex = FunctionScopes.size() - 1;
+ unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
do {
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
- DeclContext *ParentDC;
- if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC))
- ParentDC = DC->getParent();
- else if (isa<CXXMethodDecl>(DC) &&
- cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call &&
- cast<CXXRecordDecl>(DC->getParent())->isLambda())
- ParentDC = DC->getParent()->getParent();
- else {
- if (BuildAndDiagnose)
- diagnoseUncapturableValueReference(*this, Loc, Var, DC);
- return true;
- }
+ DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var,
+ ExprLoc,
+ BuildAndDiagnose,
+ *this);
+ if (!ParentDC) return true;
+
+ FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex];
+ CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI);
- CapturingScopeInfo *CSI =
- cast<CapturingScopeInfo>(FunctionScopes[FunctionScopesIndex]);
// Check whether we've already captured it.
- if (CSI->CaptureMap.count(Var)) {
- // If we found a capture, any subcaptures are nested.
- Nested = true;
-
- // Retrieve the capture type for this variable.
- CaptureType = CSI->getCapture(Var).getCaptureType();
-
- // Compute the type of an expression that refers to this variable.
- DeclRefType = CaptureType.getNonReferenceType();
-
- const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
- if (Cap.isCopyCapture() &&
- !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable))
- DeclRefType.addConst();
+ if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
+ DeclRefType))
break;
- }
-
- bool IsBlock = isa<BlockScopeInfo>(CSI);
- bool IsLambda = isa<LambdaScopeInfo>(CSI);
-
- // Lambdas are not allowed to capture unnamed variables
- // (e.g. anonymous unions).
- // FIXME: The C++11 rule don't actually state this explicitly, but I'm
- // assuming that's the intent.
- if (IsLambda && !Var->getDeclName()) {
+ // If we are instantiating a generic lambda call operator body,
+ // we do not want to capture new variables. What was captured
+ // during either a lambdas transformation or initial parsing
+ // should be used.
+ if (isGenericLambdaCallOperatorSpecialization(DC)) {
if (BuildAndDiagnose) {
- Diag(Loc, diag::err_lambda_capture_anonymous_var);
- Diag(Var->getLocation(), diag::note_declared_at);
- }
- return true;
- }
-
- // Prohibit variably-modified types; they're difficult to deal with.
- if (Var->getType()->isVariablyModifiedType()) {
- if (BuildAndDiagnose) {
- if (IsBlock)
- Diag(Loc, diag::err_ref_vm_type);
- else
- Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
- return true;
- }
- // Prohibit structs with flexible array members too.
- // We cannot capture what is in the tail end of the struct.
- if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) {
- if (VTTy->getDecl()->hasFlexibleArrayMember()) {
- if (BuildAndDiagnose) {
- if (IsBlock)
- Diag(Loc, diag::err_ref_flexarray_type);
- else
- Diag(Loc, diag::err_lambda_capture_flexarray_type)
- << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
- return true;
- }
- }
- // Lambdas are not allowed to capture __block variables; they don't
- // support the expected semantics.
- if (IsLambda && HasBlocksAttr) {
- if (BuildAndDiagnose) {
- Diag(Loc, diag::err_lambda_capture_block)
- << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
+ if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
+ Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
+ Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl);
+ } else
+ diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC);
}
return true;
}
-
+ // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
+ // certain types of variables (unnamed, variably modified types etc.)
+ // so check for eligibility.
+ if (!isVariableCapturable(CSI, Var, ExprLoc, BuildAndDiagnose, *this))
+ return true;
+
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) {
- // No capture-default
+ // No capture-default, and this is not an explicit capture
+ // so cannot capture this variable.
if (BuildAndDiagnose) {
- Diag(Loc, diag::err_lambda_impcap) << Var->getDeclName();
+ Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(),
diag::note_lambda_decl);
+ // FIXME: If we error out because an outer lambda can not implicitly
+ // capture a variable that an inner lambda explicitly captures, we
+ // should have the inner lambda do the explicit capture - because
+ // it makes for cleaner diagnostics later. This would purely be done
+ // so that the diagnostic does not misleadingly claim that a variable
+ // can not be captured by a lambda implicitly even though it is captured
+ // explicitly. Suggestion:
+ // - create const bool VariableCaptureWasInitiallyExplicit = Explicit
+ // at the function head
+ // - cache the StartingDeclContext - this must be a lambda
+ // - captureInLambda in the innermost lambda the variable.
}
return true;
}
@@ -11243,203 +11924,37 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
Explicit = false;
} while (!Var->getDeclContext()->Equals(DC));
- // Walk back down the scope stack, computing the type of the capture at
- // each step, checking type-specific requirements, and adding captures if
- // requested.
- for (unsigned I = ++FunctionScopesIndex, N = FunctionScopes.size(); I != N;
+ // Walk back down the scope stack, (e.g. from outer lambda to inner lambda)
+ // computing the type of the capture at each step, checking type-specific
+ // requirements, and adding captures if requested.
+ // If the variable had already been captured previously, we start capturing
+ // at the lambda nested within that one.
+ for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; I != N;
++I) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[I]);
- // Compute the type of the capture and of a reference to the capture within
- // this scope.
- if (isa<BlockScopeInfo>(CSI)) {
- Expr *CopyExpr = 0;
- bool ByRef = false;
-
- // Blocks are not allowed to capture arrays.
- if (CaptureType->isArrayType()) {
- if (BuildAndDiagnose) {
- Diag(Loc, diag::err_ref_array_type);
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
- return true;
- }
-
- // Forbid the block-capture of autoreleasing variables.
- if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
- if (BuildAndDiagnose) {
- Diag(Loc, diag::err_arc_autoreleasing_capture)
- << /*block*/ 0;
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
+ if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(CSI)) {
+ if (!captureInBlock(BSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
+ DeclRefType, Nested, *this))
return true;
- }
-
- if (HasBlocksAttr || CaptureType->isReferenceType()) {
- // Block capture by reference does not change the capture or
- // declaration reference types.
- ByRef = true;
- } else {
- // Block capture by copy introduces 'const'.
- CaptureType = CaptureType.getNonReferenceType().withConst();
- DeclRefType = CaptureType;
-
- if (getLangOpts().CPlusPlus && BuildAndDiagnose) {
- if (const RecordType *Record = DeclRefType->getAs<RecordType>()) {
- // The capture logic needs the destructor, so make sure we mark it.
- // Usually this is unnecessary because most local variables have
- // their destructors marked at declaration time, but parameters are
- // an exception because it's technically only the call site that
- // actually requires the destructor.
- if (isa<ParmVarDecl>(Var))
- FinalizeVarWithDestructor(Var, Record);
-
- // Enter a new evaluation context to insulate the copy
- // full-expression.
- EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
-
- // According to the blocks spec, the capture of a variable from
- // the stack requires a const copy constructor. This is not true
- // of the copy/move done to move a __block variable to the heap.
- Expr *DeclRef = new (Context) DeclRefExpr(Var, Nested,
- DeclRefType.withConst(),
- VK_LValue, Loc);
-
- ExprResult Result
- = PerformCopyInitialization(
- InitializedEntity::InitializeBlock(Var->getLocation(),
- CaptureType, false),
- Loc, Owned(DeclRef));
-
- // Build a full-expression copy expression if initialization
- // succeeded and used a non-trivial constructor. Recover from
- // errors by pretending that the copy isn't necessary.
- if (!Result.isInvalid() &&
- !cast<CXXConstructExpr>(Result.get())->getConstructor()
- ->isTrivial()) {
- Result = MaybeCreateExprWithCleanups(Result);
- CopyExpr = Result.take();
- }
- }
- }
- }
-
- // Actually capture the variable.
- if (BuildAndDiagnose)
- CSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc,
- SourceLocation(), CaptureType, CopyExpr);
Nested = true;
- continue;
- }
-
- if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
- // By default, capture variables by reference.
- bool ByRef = true;
- // Using an LValue reference type is consistent with Lambdas (see below).
- CaptureType = Context.getLValueReferenceType(DeclRefType);
-
- Expr *CopyExpr = 0;
- if (BuildAndDiagnose) {
- ExprResult Result = captureInCapturedRegion(*this, RSI, Var,
- CaptureType, DeclRefType,
- Loc, Nested);
- if (!Result.isInvalid())
- CopyExpr = Result.take();
- }
-
- // Actually capture the variable.
- if (BuildAndDiagnose)
- CSI->addCapture(Var, /*isBlock*/false, ByRef, Nested, Loc,
- SourceLocation(), CaptureType, CopyExpr);
+ } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+ if (!captureInCapturedRegion(RSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
+ DeclRefType, Nested, *this))
+ return true;
Nested = true;
- continue;
- }
-
- LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
-
- // Determine whether we are capturing by reference or by value.
- bool ByRef = false;
- if (I == N - 1 && Kind != TryCapture_Implicit) {
- ByRef = (Kind == TryCapture_ExplicitByRef);
- } else {
- ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
- }
-
- // Compute the type of the field that will capture this variable.
- if (ByRef) {
- // C++11 [expr.prim.lambda]p15:
- // An entity is captured by reference if it is implicitly or
- // explicitly captured but not captured by copy. It is
- // unspecified whether additional unnamed non-static data
- // members are declared in the closure type for entities
- // captured by reference.
- //
- // FIXME: It is not clear whether we want to build an lvalue reference
- // to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears
- // to do the former, while EDG does the latter. Core issue 1249 will
- // clarify, but for now we follow GCC because it's a more permissive and
- // easily defensible position.
- CaptureType = Context.getLValueReferenceType(DeclRefType);
} else {
- // C++11 [expr.prim.lambda]p14:
- // For each entity captured by copy, an unnamed non-static
- // data member is declared in the closure type. The
- // declaration order of these members is unspecified. The type
- // of such a data member is the type of the corresponding
- // captured entity if the entity is not a reference to an
- // object, or the referenced type otherwise. [Note: If the
- // captured entity is a reference to a function, the
- // corresponding data member is also a reference to a
- // function. - end note ]
- if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()){
- if (!RefType->getPointeeType()->isFunctionType())
- CaptureType = RefType->getPointeeType();
- }
-
- // Forbid the lambda copy-capture of autoreleasing variables.
- if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
- if (BuildAndDiagnose) {
- Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1;
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
+ LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
+ if (!captureInLambda(LSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
+ DeclRefType, Nested, Kind, EllipsisLoc,
+ /*IsTopScope*/I == N - 1, *this))
return true;
- }
- }
-
- // Capture this variable in the lambda.
- Expr *CopyExpr = 0;
- if (BuildAndDiagnose) {
- ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType,
- DeclRefType, Loc,
- Nested);
- if (!Result.isInvalid())
- CopyExpr = Result.take();
- }
-
- // Compute the type of a reference to this captured variable.
- if (ByRef)
- DeclRefType = CaptureType.getNonReferenceType();
- else {
- // C++ [expr.prim.lambda]p5:
- // The closure type for a lambda-expression has a public inline
- // function call operator [...]. This function call operator is
- // declared const (9.3.1) if and only if the lambda-expression’s
- // parameter-declaration-clause is not followed by mutable.
- DeclRefType = CaptureType.getNonReferenceType();
- if (!LSI->Mutable && !CaptureType->isReferenceType())
- DeclRefType.addConst();
+ Nested = true;
}
-
- // Add the capture.
- if (BuildAndDiagnose)
- CSI->addCapture(Var, /*IsBlock=*/false, ByRef, Nested, Loc,
- EllipsisLoc, CaptureType, CopyExpr);
- Nested = true;
}
-
return false;
}
@@ -11449,7 +11964,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
QualType DeclRefType;
return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,
/*BuildAndDiagnose=*/true, CaptureType,
- DeclRefType);
+ DeclRefType, 0);
}
QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
@@ -11458,28 +11973,36 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
// Determine whether we can capture this variable.
if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
- /*BuildAndDiagnose=*/false, CaptureType, DeclRefType))
+ /*BuildAndDiagnose=*/false, CaptureType,
+ DeclRefType, 0))
return QualType();
return DeclRefType;
}
-static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var,
- SourceLocation Loc) {
- // Keep track of used but undefined variables.
- // FIXME: We shouldn't suppress this warning for static data members.
- if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
- Var->getLinkage() != ExternalLinkage &&
- !(Var->isStaticDataMember() && Var->hasInit())) {
- SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
- if (old.isInvalid()) old = Loc;
- }
- SemaRef.tryCaptureVariable(Var, Loc);
- Var->setUsed(true);
+// If either the type of the variable or the initializer is dependent,
+// return false. Otherwise, determine whether the variable is a constant
+// expression. Use this if you need to know if a variable that might or
+// might not be dependent is truly a constant expression.
+static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var,
+ ASTContext &Context) {
+
+ if (Var->getType()->isDependentType())
+ return false;
+ const VarDecl *DefVD = 0;
+ Var->getAnyInitializer(DefVD);
+ if (!DefVD)
+ return false;
+ EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt();
+ Expr *Init = cast<Expr>(Eval->Value);
+ if (Init->isValueDependent())
+ return false;
+ return IsVariableAConstantExpression(Var, Context);
}
+
void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
// Per C++11 [basic.def.odr], a variable is odr-used "unless it is
// an object that satisfies the requirements for appearing in a
@@ -11487,6 +12010,22 @@ void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
// is immediately applied." This function handles the lvalue-to-rvalue
// conversion part.
MaybeODRUseExprs.erase(E->IgnoreParens());
+
+ // If we are in a lambda, check if this DeclRefExpr or MemberExpr refers
+ // to a variable that is a constant expression, and if so, identify it as
+ // a reference to a variable that does not involve an odr-use of that
+ // variable.
+ if (LambdaScopeInfo *LSI = getCurLambda()) {
+ Expr *SansParensExpr = E->IgnoreParens();
+ VarDecl *Var = 0;
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))
+ Var = dyn_cast<VarDecl>(DRE->getFoundDecl());
+ else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr))
+ Var = dyn_cast<VarDecl>(ME->getMemberDecl());
+
+ if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context))
+ LSI->markVariableExprAsNonODRUsed(SansParensExpr);
+ }
}
ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
@@ -11517,46 +12056,105 @@ void Sema::CleanupVarDeclMarking() {
llvm_unreachable("Unexpcted expression");
}
- MarkVarDeclODRUsed(*this, Var, Loc);
+ MarkVarDeclODRUsed(Var, Loc, *this, /*MaxFunctionScopeIndex Pointer*/ 0);
}
MaybeODRUseExprs.clear();
}
-// Mark a VarDecl referenced, and perform the necessary handling to compute
-// odr-uses.
+
static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
VarDecl *Var, Expr *E) {
+ assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) &&
+ "Invalid Expr argument to DoMarkVarDeclReferenced");
Var->setReferenced();
- if (!IsPotentiallyEvaluatedContext(SemaRef))
- return;
-
- // Implicit instantiation of static data members of class templates.
- if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) {
- MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid();
- if (MSInfo->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
- (!AlreadyInstantiated ||
- Var->isUsableInConstantExpressions(SemaRef.Context))) {
- if (!AlreadyInstantiated) {
+ // If the context is not PotentiallyEvaluated and not Unevaluated
+ // (i.e PotentiallyEvaluatedIfUsed) do not bother to consider variables
+ // in this context for odr-use unless we are within a lambda.
+ // If we don't know whether the context is potentially evaluated or not
+ // (for e.g., if we're in a generic lambda), we want to add a potential
+ // capture and eventually analyze for odr-use.
+ // We should also be able to analyze certain constructs in a non-generic
+ // lambda setting for potential odr-use and capture violation:
+ // template<class T> void foo(T t) {
+ // auto L = [](int i) { return t; };
+ // }
+ //
+ if (!IsPotentiallyEvaluatedContext(SemaRef)) {
+
+ if (SemaRef.isUnevaluatedContext()) return;
+
+ const bool refersToEnclosingScope =
+ (SemaRef.CurContext != Var->getDeclContext() &&
+ Var->getDeclContext()->isFunctionOrMethod());
+ if (!refersToEnclosingScope) return;
+
+ if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {
+ // If a variable could potentially be odr-used, defer marking it so
+ // until we finish analyzing the full expression for any lvalue-to-rvalue
+ // or discarded value conversions that would obviate odr-use.
+ // Add it to the list of potential captures that will be analyzed
+ // later (ActOnFinishFullExpr) for eventual capture and odr-use marking
+ // unless the variable is a reference that was initialized by a constant
+ // expression (this will never need to be captured or odr-used).
+ const bool IsConstantExpr = IsVariableNonDependentAndAConstantExpression(
+ Var, SemaRef.Context);
+ assert(E && "Capture variable should be used in an expression.");
+ if (!IsConstantExpr || !Var->getType()->isReferenceType())
+ LSI->addPotentialCapture(E->IgnoreParens());
+ }
+ return;
+ }
+
+ VarTemplateSpecializationDecl *VarSpec =
+ dyn_cast<VarTemplateSpecializationDecl>(Var);
+ assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
+ "Can't instantiate a partial template specialization.");
+
+ // Implicit instantiation of static data members, static data member
+ // templates of class templates, and variable template specializations.
+ // Delay instantiations of variable templates, except for those
+ // that could be used in a constant expression.
+ TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
+ if (isTemplateInstantiation(TSK)) {
+ bool TryInstantiating = TSK == TSK_ImplicitInstantiation;
+
+ if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) {
+ if (Var->getPointOfInstantiation().isInvalid()) {
// This is a modification of an existing AST node. Notify listeners.
if (ASTMutationListener *L = SemaRef.getASTMutationListener())
L->StaticDataMemberInstantiated(Var);
- MSInfo->setPointOfInstantiation(Loc);
+ } else if (!Var->isUsableInConstantExpressions(SemaRef.Context))
+ // Don't bother trying to instantiate it again, unless we might need
+ // its initializer before we get to the end of the TU.
+ TryInstantiating = false;
+ }
+
+ if (Var->getPointOfInstantiation().isInvalid())
+ Var->setTemplateSpecializationKind(TSK, Loc);
+
+ if (TryInstantiating) {
+ SourceLocation PointOfInstantiation = Var->getPointOfInstantiation();
+ bool InstantiationDependent = false;
+ bool IsNonDependent =
+ VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
+ VarSpec->getTemplateArgsInfo(), InstantiationDependent)
+ : true;
+
+ // Do not instantiate specializations that are still type-dependent.
+ if (IsNonDependent) {
+ if (Var->isUsableInConstantExpressions(SemaRef.Context)) {
+ // Do not defer instantiations of variables which could be used in a
+ // constant expression.
+ SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
+ } else {
+ SemaRef.PendingInstantiations
+ .push_back(std::make_pair(Var, PointOfInstantiation));
+ }
}
- SourceLocation PointOfInstantiation = MSInfo->getPointOfInstantiation();
- if (Var->isUsableInConstantExpressions(SemaRef.Context))
- // Do not defer instantiations of variables which could be used in a
- // constant expression.
- SemaRef.InstantiateStaticDataMemberDefinition(PointOfInstantiation,Var);
- else
- SemaRef.PendingInstantiations.push_back(
- std::make_pair(Var, PointOfInstantiation));
}
}
-
// Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies
// the requirements for appearing in a constant expression (5.19) and, if
// it is an object, the lvalue-to-rvalue conversion (4.1)
@@ -11565,14 +12163,16 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// Note that we use the C++11 definition everywhere because nothing in
// C++03 depends on whether we get the C++03 version correct. The second
// part does not apply to references, since they are not objects.
- const VarDecl *DefVD;
- if (E && !isa<ParmVarDecl>(Var) &&
- Var->isUsableInConstantExpressions(SemaRef.Context) &&
- Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) {
+ if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) {
+ // A reference initialized by a constant expression can never be
+ // odr-used, so simply ignore it.
+ // But a non-reference might get odr-used if it doesn't undergo
+ // an lvalue-to-rvalue or is discarded, so track it.
if (!Var->getType()->isReferenceType())
SemaRef.MaybeODRUseExprs.insert(E);
- } else
- MarkVarDeclODRUsed(SemaRef, Var, Loc);
+ }
+ else
+ MarkVarDeclODRUsed(Var, Loc, SemaRef, /*MaxFunctionScopeIndex ptr*/0);
}
/// \brief Mark a variable referenced, and check whether it is odr-used
@@ -11889,7 +12489,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
Selector Sel = ME->getSelector();
// self = [<foo> init...]
- if (isSelfExpr(Op->getLHS()) && Sel.getNameForSlot(0).startswith("init"))
+ if (isSelfExpr(Op->getLHS()) && ME->getMethodFamily() == OMF_init)
diagnostic = diag::warn_condition_is_idiomatic_assignment;
// <foo> = [<bar> nextObject]
@@ -12204,15 +12804,49 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
assert(E->getObjectKind() == OK_Ordinary);
// Rebuild the function type, replacing the result type with DestType.
- if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType))
- DestType =
- S.Context.getFunctionType(DestType,
- ArrayRef<QualType>(Proto->arg_type_begin(),
- Proto->getNumArgs()),
- Proto->getExtProtoInfo());
- else
+ const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType);
+ if (Proto) {
+ // __unknown_anytype(...) is a special case used by the debugger when
+ // it has no idea what a function's signature is.
+ //
+ // We want to build this call essentially under the K&R
+ // unprototyped rules, but making a FunctionNoProtoType in C++
+ // would foul up all sorts of assumptions. However, we cannot
+ // simply pass all arguments as variadic arguments, nor can we
+ // portably just call the function under a non-variadic type; see
+ // the comment on IR-gen's TargetInfo::isNoProtoCallVariadic.
+ // However, it turns out that in practice it is generally safe to
+ // call a function declared as "A foo(B,C,D);" under the prototype
+ // "A foo(B,C,D,...);". The only known exception is with the
+ // Windows ABI, where any variadic function is implicitly cdecl
+ // regardless of its normal CC. Therefore we change the parameter
+ // types to match the types of the arguments.
+ //
+ // This is a hack, but it is far superior to moving the
+ // corresponding target-specific code from IR-gen to Sema/AST.
+
+ ArrayRef<QualType> ParamTypes = Proto->getArgTypes();
+ SmallVector<QualType, 8> ArgTypes;
+ if (ParamTypes.empty() && Proto->isVariadic()) { // the special case
+ ArgTypes.reserve(E->getNumArgs());
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
+ Expr *Arg = E->getArg(i);
+ QualType ArgType = Arg->getType();
+ if (E->isLValue()) {
+ ArgType = S.Context.getLValueReferenceType(ArgType);
+ } else if (E->isXValue()) {
+ ArgType = S.Context.getRValueReferenceType(ArgType);
+ }
+ ArgTypes.push_back(ArgType);
+ }
+ ParamTypes = ArgTypes;
+ }
+ DestType = S.Context.getFunctionType(DestType, ParamTypes,
+ Proto->getExtProtoInfo());
+ } else {
DestType = S.Context.getFunctionNoProtoType(DestType,
FnType->getExtInfo());
+ }
// Rebuild the appropriate pointer-to-function type.
switch (Kind) {
@@ -12345,6 +12979,8 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
return ExprError();
}
+ // Modifying the declaration like this is friendly to IR-gen but
+ // also really dangerous.
VD->setType(DestType);
E->setType(Type);
E->setValueKind(ValueKind);
OpenPOWER on IntegriCloud