1,444 changes: 875 additions & 569 deletions clang/lib/Sema/SemaDeclObjC.cpp

Large diffs are not rendered by default.

559 changes: 46 additions & 513 deletions clang/lib/Sema/SemaExpr.cpp

Large diffs are not rendered by default.

17 changes: 9 additions & 8 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/APInt.h"
Expand Down Expand Up @@ -4619,10 +4620,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,

if (From->getType()->isObjCObjectPointerType() &&
ToType->isObjCObjectPointerType())
EmitRelatedResultTypeNote(From);
ObjC().EmitRelatedResultTypeNote(From);
} else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
!CheckObjCARCUnavailableWeakConversion(ToType,
From->getType())) {
!ObjC().CheckObjCARCUnavailableWeakConversion(ToType,
From->getType())) {
if (Action == AA_Initializing)
Diag(From->getBeginLoc(), diag::err_arc_weak_unavailable_assign);
else
Expand Down Expand Up @@ -4657,11 +4658,11 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// FIXME: doing this here is really ugly.
if (Kind == CK_BlockPointerToObjCPointerCast) {
ExprResult E = From;
(void) PrepareCastToObjCObjectPointer(E);
(void)ObjC().PrepareCastToObjCObjectPointer(E);
From = E.get();
}
if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
CheckObjCConversion(SourceRange(), NewToType, From, CCK);
ObjC().CheckObjCConversion(SourceRange(), NewToType, From, CCK);
From = ImpCastExprToType(From, NewToType, Kind, VK_PRValue, &BasePath, CCK)
.get();
break;
Expand Down Expand Up @@ -7098,7 +7099,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
return Composite;

// Similarly, attempt to find composite type of two objective-c pointers.
Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
Composite = ObjC().FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
if (!Composite.isNull())
Expand Down Expand Up @@ -8691,8 +8692,8 @@ static ExprResult attemptRecovery(Sema &SemaRef,
NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
/*TemplateArgs*/ nullptr, /*S*/ nullptr);
} else if (auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
return SemaRef.LookupInObjCMethod(R, Consumer.getScope(),
Ivar->getIdentifier());
return SemaRef.ObjC().LookupInObjCMethod(R, Consumer.getScope(),
Ivar->getIdentifier());
}
}

Expand Down
61 changes: 31 additions & 30 deletions clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenMP.h"

using namespace clang;
Expand Down Expand Up @@ -995,8 +996,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
// arrow operator was used with a dependent non-pointer object expression,
// build a CXXDependentScopeMemberExpr.
if (R.wasNotFoundInCurrentInstantiation() ||
(IsArrow && !BaseExprType->isPointerType() &&
BaseExprType->isDependentType()) ||
(R.getLookupName().getCXXOverloadedOperator() == OO_Equal &&
(SS.isSet() ? SS.getScopeRep()->isDependent()
: BaseExprType->isDependentType())))
Expand Down Expand Up @@ -1322,28 +1321,28 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
else if (const ObjCObjectPointerType *Ptr =
BaseType->getAs<ObjCObjectPointerType>())
BaseType = Ptr->getPointeeType();
else if (!BaseType->isDependentType()) {
if (BaseType->isRecordType()) {
// Recover from arrow accesses to records, e.g.:
// struct MyRecord foo;
// foo->bar
// This is actually well-formed in C++ if MyRecord has an
// overloaded operator->, but that should have been dealt with
// by now--or a diagnostic message already issued if a problem
// was encountered while looking for the overloaded operator->.
if (!S.getLangOpts().CPlusPlus) {
S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
<< BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
<< FixItHint::CreateReplacement(OpLoc, ".");
}
IsArrow = false;
} else if (BaseType->isFunctionType()) {
goto fail;
} else {
S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
<< BaseType << BaseExpr.get()->getSourceRange();
return ExprError();
else if (BaseType->isFunctionType())
goto fail;
else if (BaseType->isDependentType())
BaseType = S.Context.DependentTy;
else if (BaseType->isRecordType()) {
// Recover from arrow accesses to records, e.g.:
// struct MyRecord foo;
// foo->bar
// This is actually well-formed in C++ if MyRecord has an
// overloaded operator->, but that should have been dealt with
// by now--or a diagnostic message already issued if a problem
// was encountered while looking for the overloaded operator->.
if (!S.getLangOpts().CPlusPlus) {
S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
<< BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
<< FixItHint::CreateReplacement(OpLoc, ".");
}
IsArrow = false;
} else {
S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
<< BaseType << BaseExpr.get()->getSourceRange();
return ExprError();
}
}

Expand All @@ -1363,7 +1362,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
}

// Handle field access to simple records.
if (BaseType->getAsRecordDecl() || BaseType->isDependentType()) {
if (BaseType->getAsRecordDecl()) {
TypoExpr *TE = nullptr;
if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow,
SS, HasTemplateArgs, TemplateKWLoc, TE))
Expand All @@ -1374,6 +1373,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// failed, the lookup result will have been cleared--that combined with the
// valid-but-null ExprResult will trigger the appropriate diagnostics.
return ExprResult(TE);
} else if (BaseType->isDependentType()) {
R.setNotFoundInCurrentInstantiation();
return ExprEmpty();
}

// Handle ivar access to Objective-C objects.
Expand Down Expand Up @@ -1517,9 +1519,8 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (warn) {
if (ObjCMethodDecl *MD = S.getCurMethodDecl()) {
ObjCMethodFamily MF = MD->getMethodFamily();
warn = (MF != OMF_init && MF != OMF_dealloc &&
MF != OMF_finalize &&
!S.IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
warn = (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
!S.ObjC().IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
}
if (warn)
S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
Expand Down Expand Up @@ -1657,9 +1658,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
}

// Normal property access.
return S.HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc, MemberName,
MemberLoc, SourceLocation(), QualType(),
false);
return S.ObjC().HandleExprPropertyRefExpr(
OPT, BaseExpr.get(), OpLoc, MemberName, MemberLoc, SourceLocation(),
QualType(), false);
}

if (BaseType->isExtVectorBoolType()) {
Expand Down
1,342 changes: 914 additions & 428 deletions clang/lib/Sema/SemaExprObjC.cpp

Large diffs are not rendered by default.

17 changes: 9 additions & 8 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
Expand Down Expand Up @@ -6018,8 +6019,8 @@ static bool tryObjCWritebackConversion(Sema &S,

// Handle write-back conversion.
QualType ConvertedArgType;
if (!S.isObjCWritebackConversion(ArgType, Entity.getType(),
ConvertedArgType))
if (!S.ObjC().isObjCWritebackConversion(ArgType, Entity.getType(),
ConvertedArgType))
return false;

// We should copy unless we're passing to an argument explicitly
Expand Down Expand Up @@ -6211,10 +6212,10 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (Args.size() == 1) {
Initializer = Args[0];
if (S.getLangOpts().ObjC) {
if (S.CheckObjCBridgeRelatedConversions(Initializer->getBeginLoc(),
DestType, Initializer->getType(),
Initializer) ||
S.CheckConversionToObjCLiteral(DestType, Initializer))
if (S.ObjC().CheckObjCBridgeRelatedConversions(
Initializer->getBeginLoc(), DestType, Initializer->getType(),
Initializer) ||
S.ObjC().CheckConversionToObjCLiteral(DestType, Initializer))
Args[0] = Initializer;
}
if (!isa<InitListExpr>(Initializer))
Expand Down Expand Up @@ -9558,12 +9559,12 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity,

// Emit a possible note about the conversion failing because the
// operand is a message send with a related result type.
S.EmitRelatedResultTypeNote(op);
S.ObjC().EmitRelatedResultTypeNote(op);

// Emit a possible note about a return failing because we're
// expecting a related result type.
if (entity.getKind() == InitializedEntity::EK_Result)
S.EmitRelatedResultTypeNoteForReturn(destType);
S.ObjC().EmitRelatedResultTypeNoteForReturn(destType);
}
QualType fromType = op->getType();
QualType fromPointeeType = fromType.getCanonicalType()->getPointeeType();
Expand Down
9 changes: 0 additions & 9 deletions clang/lib/Sema/SemaLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3365,15 +3365,6 @@ NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
return R.getAsSingle<NamedDecl>();
}

/// Find the protocol with the given name, if any.
ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II,
SourceLocation IdLoc,
RedeclarationKind Redecl) {
Decl *D = LookupSingleName(TUScope, II, IdLoc,
LookupObjCProtocolName, Redecl);
return cast_or_null<ObjCProtocolDecl>(D);
}

void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
UnresolvedSetImpl &Functions) {
// C++ [over.match.oper]p3:
Expand Down
1,486 changes: 1,486 additions & 0 deletions clang/lib/Sema/SemaObjC.cpp

Large diffs are not rendered by default.

290 changes: 136 additions & 154 deletions clang/lib/Sema/SemaObjCProperty.cpp

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,33 @@ bool checkAlreadyHasClauseOfKind(
return false;
}

/// Implement check from OpenACC3.3: section 2.5.4:
/// Only the async, wait, num_gangs, num_workers, and vector_length clauses may
/// follow a device_type clause.
bool checkValidAfterDeviceType(
SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause,
const SemaOpenACC::OpenACCParsedClause &NewClause) {
// This is only a requirement on compute constructs so far, so this is fine
// otherwise.
if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind()))
return false;
switch (NewClause.getClauseKind()) {
case OpenACCClauseKind::Async:
case OpenACCClauseKind::Wait:
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::VectorLength:
case OpenACCClauseKind::DType:
case OpenACCClauseKind::DeviceType:
return false;
default:
S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type)
<< NewClause.getClauseKind() << DeviceTypeClause.getClauseKind();
S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here);
return true;
}
}

} // namespace

SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
Expand All @@ -273,6 +300,17 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
return nullptr;
}

if (const auto *DevTypeClause =
llvm::find_if(ExistingClauses,
[&](const OpenACCClause *C) {
return isa<OpenACCDeviceTypeClause>(C);
});
DevTypeClause != ExistingClauses.end()) {
if (checkValidAfterDeviceType(
*this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))
return nullptr;
}

switch (Clause.getClauseKind()) {
case OpenACCClauseKind::Default: {
// Restrictions only properly implemented on 'compute' constructs, and
Expand Down Expand Up @@ -651,6 +689,23 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
Clause.getDevNumExpr(), Clause.getQueuesLoc(), Clause.getQueueIdExprs(),
Clause.getEndLoc());
}
case OpenACCClauseKind::DType:
case OpenACCClauseKind::DeviceType: {
// Restrictions only properly implemented on 'compute' constructs, and
// 'compute' constructs are the only construct that can do anything with
// this yet, so skip/treat as unimplemented in this case.
if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
break;

// TODO OpenACC: Once we get enough of the CodeGen implemented that we have
// a source for the list of valid architectures, we need to warn on unknown
// identifiers here.

return OpenACCDeviceTypeClause::Create(
getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(),
Clause.getLParenLoc(), Clause.getDeviceTypeArchitectures(),
Clause.getEndLoc());
}
default:
break;
}
Expand Down
171 changes: 133 additions & 38 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15109,13 +15109,13 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc) {
ASTContext &Context = getASTContext();
auto SizesClauses =
OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
if (SizesClauses.empty()) {
// A missing 'sizes' clause is already reported by the parser.
Scope *CurScope = SemaRef.getCurScope();

const auto *SizesClause =
OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
if (!SizesClause ||
llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
return StmtError();
}
const OMPSizesClause *SizesClause = *SizesClauses.begin();
unsigned NumLoops = SizesClause->getNumSizes();

// Empty statement should only be possible if there already was an error.
Expand All @@ -15136,7 +15136,15 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
NumLoops, AStmt, nullptr, nullptr);

assert(LoopHelpers.size() == NumLoops &&
"Expecting loop iteration space dimensionality to match number of "
"affected loops");
assert(OriginalInits.size() == NumLoops &&
"Expecting loop iteration space dimensionality to match number of "
"affected loops");

SmallVector<Decl *, 4> PreInits;
CaptureVars CopyTransformer(SemaRef);

// Create iteration variables for the generated loops.
SmallVector<VarDecl *, 4> FloorIndVars;
Expand Down Expand Up @@ -15194,36 +15202,81 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
// Once the original iteration values are set, append the innermost body.
Stmt *Inner = Body;

auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
SizesClause, CurScope](int I) -> Expr * {
Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
if (isa<ConstantExpr>(DimTileSizeExpr))
return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));

// When the tile size is not a constant but a variable, it is possible to
// pass non-positive numbers. For instance:
// \code{c}
// int a = 0;
// #pragma omp tile sizes(a)
// for (int i = 0; i < 42; ++i)
// body(i);
// \endcode
// Although there is no meaningful interpretation of the tile size, the body
// should still be executed 42 times to avoid surprises. To preserve the
// invariant that every loop iteration is executed exactly once and not
// cause an infinite loop, apply a minimum tile size of one.
// Build expr:
// \code{c}
// (TS <= 0) ? 1 : TS
// \endcode
QualType DimTy = DimTileSizeExpr->getType();
uint64_t DimWidth = Context.getTypeSize(DimTy);
IntegerLiteral *Zero = IntegerLiteral::Create(
Context, llvm::APInt::getZero(DimWidth), DimTy, {});
IntegerLiteral *One =
IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
CurScope, {}, BO_LE,
AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
Expr *MinOne = new (Context) ConditionalOperator(
Cond, {}, One, {},
AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
VK_PRValue, OK_Ordinary);
return MinOne;
};

// Create tile loops from the inside to the outside.
for (int I = NumLoops - 1; I >= 0; --I) {
OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
Expr *NumIterations = LoopHelper.NumIterations;
auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
QualType CntTy = OrigCntVar->getType();
Expr *DimTileSize = SizesClause->getSizesRefs()[I];
Scope *CurScope = SemaRef.getCurScope();

// Commonly used variables.
DeclRefExpr *TileIV = buildDeclRefExpr(SemaRef, TileIndVars[I], CntTy,
OrigCntVar->getExprLoc());
DeclRefExpr *FloorIV = buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy,
OrigCntVar->getExprLoc());
// Commonly used variables. One of the constraints of an AST is that every
// node object must appear at most once, hence we define lamdas that create
// a new AST node at every use.
auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, CntTy,
OrigCntVar]() {
return buildDeclRefExpr(SemaRef, TileIndVars[I], CntTy,
OrigCntVar->getExprLoc());
};
auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy,
OrigCntVar]() {
return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy,
OrigCntVar->getExprLoc());
};

// For init-statement: auto .tile.iv = .floor.iv
SemaRef.AddInitializerToDecl(TileIndVars[I],
SemaRef.DefaultLvalueConversion(FloorIV).get(),
/*DirectInit=*/false);
SemaRef.AddInitializerToDecl(
TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(),
/*DirectInit=*/false);
Decl *CounterDecl = TileIndVars[I];
StmtResult InitStmt = new (Context)
DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
if (!InitStmt.isUsable())
return StmtError();

// For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
// NumIterations)
ExprResult EndOfTile = SemaRef.BuildBinOp(
CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, FloorIV, DimTileSize);
// For cond-expression:
// .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
ExprResult EndOfTile =
SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
MakeFloorIVRef(), MakeDimTileSize(I));
if (!EndOfTile.isUsable())
return StmtError();
ExprResult IsPartialTile =
Expand All @@ -15238,25 +15291,28 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
ExprResult CondExpr =
SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
TileIV, MinTileAndIterSpace.get());
MakeTileIVRef(), MinTileAndIterSpace.get());
if (!CondExpr.isUsable())
return StmtError();

// For incr-statement: ++.tile.iv
ExprResult IncrStmt = SemaRef.BuildUnaryOp(
CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
if (!IncrStmt.isUsable())
return StmtError();

// Statements to set the original iteration variable's value from the
// logical iteration number.
// Generated for loop is:
// \code
// Original_for_init;
// for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
// NumIterations); ++.tile.iv) {
// for (auto .tile.iv = .floor.iv;
// .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
// ++.tile.iv) {
// Original_Body;
// Original_counter_update;
// }
// \endcode
// FIXME: If the innermost body is an loop itself, inserting these
// statements stops it being recognized as a perfectly nested loop (e.g.
// for applying tiling again). If this is the case, sink the expressions
Expand All @@ -15278,12 +15334,13 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
Expr *NumIterations = LoopHelper.NumIterations;
DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
QualType CntTy = OrigCntVar->getType();
Expr *DimTileSize = SizesClause->getSizesRefs()[I];
Scope *CurScope = SemaRef.getCurScope();

// Commonly used variables.
DeclRefExpr *FloorIV = buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy,
OrigCntVar->getExprLoc());
auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy,
OrigCntVar]() {
return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy,
OrigCntVar->getExprLoc());
};

// For init-statement: auto .floor.iv = 0
SemaRef.AddInitializerToDecl(
Expand All @@ -15298,15 +15355,16 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();

// For cond-expression: .floor.iv < NumIterations
ExprResult CondExpr = SemaRef.BuildBinOp(
CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, FloorIV, NumIterations);
ExprResult CondExpr =
SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
MakeFloorIVRef(), NumIterations);
if (!CondExpr.isUsable())
return StmtError();

// For incr-statement: .floor.iv += DimTileSize
ExprResult IncrStmt =
SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
FloorIV, DimTileSize);
MakeFloorIVRef(), MakeDimTileSize(I));
if (!IncrStmt.isUsable())
return StmtError();

Expand Down Expand Up @@ -17407,16 +17465,53 @@ OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
for (Expr *SizeExpr : SizeExprs) {
ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
if (!NumForLoopsResult.isUsable())
return nullptr;
SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);

for (Expr *&SizeExpr : SanitizedSizeExprs) {
// Skip if already sanitized, e.g. during a partial template instantiation.
if (!SizeExpr)
continue;

bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
/*StrictlyPositive=*/true);

// isNonNegativeIntegerValue returns true for non-integral types (but still
// emits error diagnostic), so check for the expected type explicitly.
QualType SizeTy = SizeExpr->getType();
if (!SizeTy->isIntegerType())
IsValid = false;

// Handling in templates is tricky. There are four possibilities to
// consider:
//
// 1a. The expression is valid and we are in a instantiated template or not
// in a template:
// Pass valid expression to be further analysed later in Sema.
// 1b. The expression is valid and we are in a template (including partial
// instantiation):
// isNonNegativeIntegerValue skipped any checks so there is no
// guarantee it will be correct after instantiation.
// ActOnOpenMPSizesClause will be called again at instantiation when
// it is not in a dependent context anymore. This may cause warnings
// to be emitted multiple times.
// 2a. The expression is invalid and we are in an instantiated template or
// not in a template:
// Invalidate the expression with a clearly wrong value (nullptr) so
// later in Sema we do not have to do the same validity analysis again
// or crash from unexpected data. Error diagnostics have already been
// emitted.
// 2b. The expression is invalid and we are in a template (including partial
// instantiation):
// Pass the invalid expression as-is, template instantiation may
// replace unexpected types/values with valid ones. The directives
// with this clause must not try to use these expressions in dependent
// contexts, but delay analysis until full instantiation.
if (!SizeExpr->isInstantiationDependent() && !IsValid)
SizeExpr = nullptr;
}

DSAStack->setAssociatedLoops(SizeExprs.size());
return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
SizeExprs);
SanitizedSizeExprs);
}

OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
Expand Down
78 changes: 6 additions & 72 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "clang/Sema/Overload.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/DenseSet.h"
Expand Down Expand Up @@ -1086,7 +1087,7 @@ namespace {
assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
Entry entry = { &E, E };
Entries.push_back(entry);
E = S.stripARCUnbridgedCast(E);
E = S.ObjC().stripARCUnbridgedCast(E);
}

void restore() {
Expand Down Expand Up @@ -1778,8 +1779,8 @@ ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType,
= getLangOpts().ObjCAutoRefCount &&
(Action == AA_Passing || Action == AA_Sending);
if (getLangOpts().ObjC)
CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType,
From->getType(), From);
ObjC().CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType,
From->getType(), From);
ImplicitConversionSequence ICS = ::TryImplicitConversion(
*this, From, ToType,
/*SuppressUserConversions=*/false,
Expand Down Expand Up @@ -2272,7 +2273,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
} else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) {
SCS.Second = ICK_Block_Pointer_Conversion;
} else if (AllowObjCWritebackConversion &&
S.isObjCWritebackConversion(FromType, ToType, FromType)) {
S.ObjC().isObjCWritebackConversion(FromType, ToType, FromType)) {
SCS.Second = ICK_Writeback_Conversion;
} else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution,
FromType, IncompatibleObjC)) {
Expand Down Expand Up @@ -3060,73 +3061,6 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
return false;
}

/// Determine whether this is an Objective-C writeback conversion,
/// used for parameter passing when performing automatic reference counting.
///
/// \param FromType The type we're converting form.
///
/// \param ToType The type we're converting to.
///
/// \param ConvertedType The type that will be produced after applying
/// this conversion.
bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType,
QualType &ConvertedType) {
if (!getLangOpts().ObjCAutoRefCount ||
Context.hasSameUnqualifiedType(FromType, ToType))
return false;

// Parameter must be a pointer to __autoreleasing (with no other qualifiers).
QualType ToPointee;
if (const PointerType *ToPointer = ToType->getAs<PointerType>())
ToPointee = ToPointer->getPointeeType();
else
return false;

Qualifiers ToQuals = ToPointee.getQualifiers();
if (!ToPointee->isObjCLifetimeType() ||
ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing ||
!ToQuals.withoutObjCLifetime().empty())
return false;

// Argument must be a pointer to __strong to __weak.
QualType FromPointee;
if (const PointerType *FromPointer = FromType->getAs<PointerType>())
FromPointee = FromPointer->getPointeeType();
else
return false;

Qualifiers FromQuals = FromPointee.getQualifiers();
if (!FromPointee->isObjCLifetimeType() ||
(FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong &&
FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak))
return false;

// Make sure that we have compatible qualifiers.
FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing);
if (!ToQuals.compatiblyIncludes(FromQuals))
return false;

// Remove qualifiers from the pointee type we're converting from; they
// aren't used in the compatibility check belong, and we'll be adding back
// qualifiers (with __autoreleasing) if the compatibility check succeeds.
FromPointee = FromPointee.getUnqualifiedType();

// The unqualified form of the pointee types must be compatible.
ToPointee = ToPointee.getUnqualifiedType();
bool IncompatibleObjC;
if (Context.typesAreCompatible(FromPointee, ToPointee))
FromPointee = ToPointee;
else if (!isObjCPointerConversion(FromPointee, ToPointee, FromPointee,
IncompatibleObjC))
return false;

/// Construct the type we're converting to, which is a pointer to
/// __autoreleasing pointee.
FromPointee = Context.getQualifiedType(FromPointee, FromQuals);
ConvertedType = Context.getPointerType(FromPointee);
return true;
}

bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
QualType& ConvertedType) {
QualType ToPointeeType;
Expand Down Expand Up @@ -7241,7 +7175,7 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance,
// a consumed argument.
if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
!param->hasAttr<CFConsumedAttr>())
argExpr = stripARCUnbridgedCast(argExpr);
argExpr = ObjC().stripARCUnbridgedCast(argExpr);

// If the parameter is __unknown_anytype, move on to the next method.
if (param->getType() == Context.UnknownAnyTy) {
Expand Down
186 changes: 53 additions & 133 deletions clang/lib/Sema/SemaPseudoObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "llvm/ADT/SmallString.h"

using namespace clang;
Expand Down Expand Up @@ -557,30 +558,31 @@ static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,

// Special case for 'self' in class method implementations.
if (PT->isObjCClassType() &&
S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
S.ObjC().isSelfExpr(const_cast<Expr *>(PRE->getBase()))) {
// This cast is safe because isSelfExpr is only true within
// methods.
ObjCMethodDecl *method =
cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
return S.LookupMethodInObjectType(sel,
S.Context.getObjCInterfaceType(method->getClassInterface()),
/*instance*/ false);
return S.ObjC().LookupMethodInObjectType(
sel, S.Context.getObjCInterfaceType(method->getClassInterface()),
/*instance*/ false);
}

return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true);
}

if (PRE->isSuperReceiver()) {
if (const ObjCObjectPointerType *PT =
PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true);

return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
return S.ObjC().LookupMethodInObjectType(sel, PRE->getSuperReceiverType(),
false);
}

assert(PRE->isClassReceiver() && "Invalid expression");
QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
return S.LookupMethodInObjectType(sel, IT, false);
return S.ObjC().LookupMethodInObjectType(sel, IT, false);
}

bool ObjCPropertyOpBuilder::isWeakProperty() const {
Expand Down Expand Up @@ -741,13 +743,13 @@ ExprResult ObjCPropertyOpBuilder::buildGet() {
if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
RefExpr->isObjectReceiver()) {
assert(InstanceReceiver || RefExpr->isSuperReceiver());
msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
GenericLoc, Getter->getSelector(),
Getter, std::nullopt);
msg = S.ObjC().BuildInstanceMessageImplicit(
InstanceReceiver, receiverType, GenericLoc, Getter->getSelector(),
Getter, std::nullopt);
} else {
msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
GenericLoc, Getter->getSelector(), Getter,
std::nullopt);
msg = S.ObjC().BuildClassMessageImplicit(
receiverType, RefExpr->isSuperReceiver(), GenericLoc,
Getter->getSelector(), Getter, std::nullopt);
}
return msg;
}
Expand Down Expand Up @@ -801,14 +803,13 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true);
if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
RefExpr->isObjectReceiver()) {
msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
GenericLoc, SetterSelector, Setter,
MultiExprArg(args, 1));
msg = S.ObjC().BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
GenericLoc, SetterSelector,
Setter, MultiExprArg(args, 1));
} else {
msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
GenericLoc,
SetterSelector, Setter,
MultiExprArg(args, 1));
msg = S.ObjC().BuildClassMessageImplicit(
receiverType, RefExpr->isSuperReceiver(), GenericLoc, SetterSelector,
Setter, MultiExprArg(args, 1));
}

if (!msg.isInvalid() && captureSetValueAsResult) {
Expand Down Expand Up @@ -836,8 +837,8 @@ ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
if (result.isInvalid()) return ExprError();

if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
Getter, RefExpr->getLocation());
S.ObjC().DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
Getter, RefExpr->getLocation());

// As a special case, if the method returns 'id', try to get
// a better type from the property.
Expand Down Expand Up @@ -925,7 +926,7 @@ ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,

// Various warnings about property assignments in ARC.
if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
S.ObjC().checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
}

Expand Down Expand Up @@ -1014,7 +1015,7 @@ ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,

// Various warnings about objc Index'ed assignments in ARC.
if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
S.ObjC().checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
}

Expand Down Expand Up @@ -1045,80 +1046,6 @@ Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
return syntacticBase;
}

/// CheckSubscriptingKind - This routine decide what type
/// of indexing represented by "FromE" is being done.
Sema::ObjCSubscriptKind
Sema::CheckSubscriptingKind(Expr *FromE) {
// If the expression already has integral or enumeration type, we're golden.
QualType T = FromE->getType();
if (T->isIntegralOrEnumerationType())
return OS_Array;

// If we don't have a class type in C++, there's no way we can get an
// expression of integral or enumeration type.
const RecordType *RecordTy = T->getAs<RecordType>();
if (!RecordTy &&
(T->isObjCObjectPointerType() || T->isVoidPointerType()))
// All other scalar cases are assumed to be dictionary indexing which
// caller handles, with diagnostics if needed.
return OS_Dictionary;
if (!getLangOpts().CPlusPlus ||
!RecordTy || RecordTy->isIncompleteType()) {
// No indexing can be done. Issue diagnostics and quit.
const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
if (isa<StringLiteral>(IndexExpr))
Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
<< T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
else
Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
<< T;
return OS_Error;
}

// We must have a complete class type.
if (RequireCompleteType(FromE->getExprLoc(), T,
diag::err_objc_index_incomplete_class_type, FromE))
return OS_Error;

// Look for a conversion to an integral, enumeration type, or
// objective-C pointer type.
int NoIntegrals=0, NoObjCIdPointers=0;
SmallVector<CXXConversionDecl *, 4> ConversionDecls;

for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())
->getVisibleConversionFunctions()) {
if (CXXConversionDecl *Conversion =
dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {
QualType CT = Conversion->getConversionType().getNonReferenceType();
if (CT->isIntegralOrEnumerationType()) {
++NoIntegrals;
ConversionDecls.push_back(Conversion);
}
else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
++NoObjCIdPointers;
ConversionDecls.push_back(Conversion);
}
}
}
if (NoIntegrals ==1 && NoObjCIdPointers == 0)
return OS_Array;
if (NoIntegrals == 0 && NoObjCIdPointers == 1)
return OS_Dictionary;
if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
// No conversion function was found. Issue diagnostic and return.
Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
<< FromE->getType();
return OS_Error;
}
Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
<< FromE->getType();
for (unsigned int i = 0; i < ConversionDecls.size(); i++)
Diag(ConversionDecls[i]->getLocation(),
diag::note_conv_function_declared_at);

return OS_Error;
}

/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
/// objects used as dictionary subscript key objects.
static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
Expand All @@ -1130,13 +1057,13 @@ static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
const IdentifierInfo *KeyIdents[] = {
&S.Context.Idents.get("objectForKeyedSubscript")};
Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
true /*instance*/);
ObjCMethodDecl *Getter = S.ObjC().LookupMethodInObjectType(
GetterSelector, ContainerT, true /*instance*/);
if (!Getter)
return;
QualType T = Getter->parameters()[0]->getType();
S.CheckObjCConversion(Key->getSourceRange(), T, Key,
CheckedConversionKind::Implicit);
S.ObjC().CheckObjCConversion(Key->getSourceRange(), T, Key,
CheckedConversionKind::Implicit);
}

bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
Expand All @@ -1151,15 +1078,15 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
BaseT->getAs<ObjCObjectPointerType>()) {
ResultType = PTy->getPointeeType();
}
Sema::ObjCSubscriptKind Res =
S.CheckSubscriptingKind(RefExpr->getKeyExpr());
if (Res == Sema::OS_Error) {
SemaObjC::ObjCSubscriptKind Res =
S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr());
if (Res == SemaObjC::OS_Error) {
if (S.getLangOpts().ObjCAutoRefCount)
CheckKeyForObjCARCConversion(S, ResultType,
RefExpr->getKeyExpr());
return false;
}
bool arrayRef = (Res == Sema::OS_Array);
bool arrayRef = (Res == SemaObjC::OS_Array);

if (ResultType.isNull()) {
S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
Expand All @@ -1181,8 +1108,8 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
}

AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
true /*instance*/);
AtIndexGetter = S.ObjC().LookupMethodInObjectType(
AtIndexGetterSelector, ResultType, true /*instance*/);

if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
AtIndexGetter = ObjCMethodDecl::Create(
Expand Down Expand Up @@ -1212,10 +1139,8 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
<< BaseExpr->getType() << 0 << arrayRef;
return false;
}
AtIndexGetter =
S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
RefExpr->getSourceRange(),
true);
AtIndexGetter = S.ObjC().LookupInstanceMethodInGlobalPool(
AtIndexGetterSelector, RefExpr->getSourceRange(), true);
}

if (AtIndexGetter) {
Expand Down Expand Up @@ -1253,15 +1178,15 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
ResultType = PTy->getPointeeType();
}

Sema::ObjCSubscriptKind Res =
S.CheckSubscriptingKind(RefExpr->getKeyExpr());
if (Res == Sema::OS_Error) {
SemaObjC::ObjCSubscriptKind Res =
S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr());
if (Res == SemaObjC::OS_Error) {
if (S.getLangOpts().ObjCAutoRefCount)
CheckKeyForObjCARCConversion(S, ResultType,
RefExpr->getKeyExpr());
return false;
}
bool arrayRef = (Res == Sema::OS_Array);
bool arrayRef = (Res == SemaObjC::OS_Array);

if (ResultType.isNull()) {
S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
Expand All @@ -1284,8 +1209,8 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
&S.Context.Idents.get("atIndexedSubscript")};
AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
}
AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
true /*instance*/);
AtIndexSetter = S.ObjC().LookupMethodInObjectType(
AtIndexSetterSelector, ResultType, true /*instance*/);

if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
TypeSourceInfo *ReturnTInfo = nullptr;
Expand Down Expand Up @@ -1327,10 +1252,8 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
<< BaseExpr->getType() << 1 << arrayRef;
return false;
}
AtIndexSetter =
S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
RefExpr->getSourceRange(),
true);
AtIndexSetter = S.ObjC().LookupInstanceMethodInGlobalPool(
AtIndexSetterSelector, RefExpr->getSourceRange(), true);
}

bool err = false;
Expand Down Expand Up @@ -1388,10 +1311,9 @@ ExprResult ObjCSubscriptOpBuilder::buildGet() {
assert(InstanceBase);
if (AtIndexGetter)
S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc);
msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
GenericLoc,
AtIndexGetterSelector, AtIndexGetter,
MultiExprArg(args, 1));
msg = S.ObjC().BuildInstanceMessageImplicit(
InstanceBase, receiverType, GenericLoc, AtIndexGetterSelector,
AtIndexGetter, MultiExprArg(args, 1));
return msg;
}

Expand All @@ -1413,11 +1335,9 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
Expr *args[] = { op, Index };

// Build a message-send.
ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
GenericLoc,
AtIndexSetterSelector,
AtIndexSetter,
MultiExprArg(args, 2));
ExprResult msg = S.ObjC().BuildInstanceMessageImplicit(
InstanceBase, receiverType, GenericLoc, AtIndexSetterSelector,
AtIndexSetter, MultiExprArg(args, 2));

if (!msg.isInvalid() && captureSetValueAsResult) {
ObjCMessageExpr *msgExpr =
Expand Down
307 changes: 4 additions & 303 deletions clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenMP.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
Expand Down Expand Up @@ -2236,165 +2237,6 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
return StmtResult(static_cast<Stmt*>(FullExpr.get()));
}

ExprResult
Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
if (!collection)
return ExprError();

ExprResult result = CorrectDelayedTyposInExpr(collection);
if (!result.isUsable())
return ExprError();
collection = result.get();

// Bail out early if we've got a type-dependent expression.
if (collection->isTypeDependent()) return collection;

// Perform normal l-value conversion.
result = DefaultFunctionArrayLvalueConversion(collection);
if (result.isInvalid())
return ExprError();
collection = result.get();

// The operand needs to have object-pointer type.
// TODO: should we do a contextual conversion?
const ObjCObjectPointerType *pointerType =
collection->getType()->getAs<ObjCObjectPointerType>();
if (!pointerType)
return Diag(forLoc, diag::err_collection_expr_type)
<< collection->getType() << collection->getSourceRange();

// Check that the operand provides
// - countByEnumeratingWithState:objects:count:
const ObjCObjectType *objectType = pointerType->getObjectType();
ObjCInterfaceDecl *iface = objectType->getInterface();

// If we have a forward-declared type, we can't do this check.
// Under ARC, it is an error not to have a forward-declared class.
if (iface &&
(getLangOpts().ObjCAutoRefCount
? RequireCompleteType(forLoc, QualType(objectType, 0),
diag::err_arc_collection_forward, collection)
: !isCompleteType(forLoc, QualType(objectType, 0)))) {
// Otherwise, if we have any useful type information, check that
// the type declares the appropriate method.
} else if (iface || !objectType->qual_empty()) {
const IdentifierInfo *selectorIdents[] = {
&Context.Idents.get("countByEnumeratingWithState"),
&Context.Idents.get("objects"), &Context.Idents.get("count")};
Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);

ObjCMethodDecl *method = nullptr;

// If there's an interface, look in both the public and private APIs.
if (iface) {
method = iface->lookupInstanceMethod(selector);
if (!method) method = iface->lookupPrivateMethod(selector);
}

// Also check protocol qualifiers.
if (!method)
method = LookupMethodInQualifiedType(selector, pointerType,
/*instance*/ true);

// If we didn't find it anywhere, give up.
if (!method) {
Diag(forLoc, diag::warn_collection_expr_type)
<< collection->getType() << selector << collection->getSourceRange();
}

// TODO: check for an incompatible signature?
}

// Wrap up any cleanups in the expression.
return collection;
}

StmtResult
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
Stmt *First, Expr *collection,
SourceLocation RParenLoc) {
setFunctionHasBranchProtectedScope();

ExprResult CollectionExprResult =
CheckObjCForCollectionOperand(ForLoc, collection);

if (First) {
QualType FirstType;
if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) {
if (!DS->isSingleDecl())
return StmtError(Diag((*DS->decl_begin())->getLocation(),
diag::err_toomany_element_decls));

VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl());
if (!D || D->isInvalidDecl())
return StmtError();

FirstType = D->getType();
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
// declare identifiers for objects having storage class 'auto' or
// 'register'.
if (!D->hasLocalStorage())
return StmtError(Diag(D->getLocation(),
diag::err_non_local_variable_decl_in_for));

// If the type contained 'auto', deduce the 'auto' to 'id'.
if (FirstType->getContainedAutoType()) {
SourceLocation Loc = D->getLocation();
OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue);
Expr *DeducedInit = &OpaqueId;
TemplateDeductionInfo Info(Loc);
FirstType = QualType();
TemplateDeductionResult Result = DeduceAutoType(
D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info);
if (Result != TemplateDeductionResult::Success &&
Result != TemplateDeductionResult::AlreadyDiagnosed)
DiagnoseAutoDeductionFailure(D, DeducedInit);
if (FirstType.isNull()) {
D->setInvalidDecl();
return StmtError();
}

D->setType(FirstType);

if (!inTemplateInstantiation()) {
SourceLocation Loc =
D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
Diag(Loc, diag::warn_auto_var_is_id)
<< D->getDeclName();
}
}

} else {
Expr *FirstE = cast<Expr>(First);
if (!FirstE->isTypeDependent() && !FirstE->isLValue())
return StmtError(
Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue)
<< First->getSourceRange());

FirstType = static_cast<Expr*>(First)->getType();
if (FirstType.isConstQualified())
Diag(ForLoc, diag::err_selector_element_const_type)
<< FirstType << First->getSourceRange();
}
if (!FirstType->isDependentType() &&
!FirstType->isObjCObjectPointerType() &&
!FirstType->isBlockPointerType())
return StmtError(Diag(ForLoc, diag::err_selector_element_type)
<< FirstType << First->getSourceRange());
}

if (CollectionExprResult.isInvalid())
return StmtError();

CollectionExprResult =
ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false);
if (CollectionExprResult.isInvalid())
return StmtError();

return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(),
nullptr, ForLoc, RParenLoc);
}

/// Finish building a variable declaration for a for-range statement.
/// \return true if an error occurs.
static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
Expand Down Expand Up @@ -2432,7 +2274,7 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
// FIXME: ARC may want to turn this into 'const __unsafe_unretained' if
// we're doing the equivalent of fast iteration.
if (SemaRef.getLangOpts().ObjCAutoRefCount &&
SemaRef.inferObjCARCLifetime(Decl))
SemaRef.ObjC().inferObjCARCLifetime(Decl))
Decl->setInvalidDecl();

SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false);
Expand Down Expand Up @@ -2526,7 +2368,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(
if (InitStmt)
return Diag(InitStmt->getBeginLoc(), diag::err_objc_for_range_init_stmt)
<< InitStmt->getSourceRange();
return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc);
return ObjC().ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc);
}

DeclStmt *DS = dyn_cast<DeclStmt>(First);
Expand Down Expand Up @@ -3107,17 +2949,6 @@ StmtResult Sema::BuildCXXForRangeStmt(
ColonLoc, RParenLoc);
}

/// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach
/// statement.
StmtResult Sema::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) {
if (!S || !B)
return StmtError();
ObjCForCollectionStmt * ForStmt = cast<ObjCForCollectionStmt>(S);

ForStmt->setBody(B);
return S;
}

// Warn when the loop variable is a const reference that creates a copy.
// Suggest using the non-reference type for copies. If a copy can be prevented
// suggest the const reference type that would do so.
Expand Down Expand Up @@ -3307,7 +3138,7 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) {
return StmtError();

if (isa<ObjCForCollectionStmt>(S))
return FinishObjCForCollectionStmt(S, B);
return ObjC().FinishObjCForCollectionStmt(S, B);

CXXForRangeStmt *ForStmt = cast<CXXForRangeStmt>(S);
ForStmt->setBody(B);
Expand Down Expand Up @@ -4301,130 +4132,6 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
return Result;
}

StmtResult
Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
SourceLocation RParen, Decl *Parm,
Stmt *Body) {
VarDecl *Var = cast_or_null<VarDecl>(Parm);
if (Var && Var->isInvalidDecl())
return StmtError();

return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body);
}

StmtResult
Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {
return new (Context) ObjCAtFinallyStmt(AtLoc, Body);
}

StmtResult
Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
MultiStmtArg CatchStmts, Stmt *Finally) {
if (!getLangOpts().ObjCExceptions)
Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";

// Objective-C try is incompatible with SEH __try.
sema::FunctionScopeInfo *FSI = getCurFunction();
if (FSI->FirstSEHTryLoc.isValid()) {
Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1;
Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";
}

FSI->setHasObjCTry(AtLoc);
unsigned NumCatchStmts = CatchStmts.size();
return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
NumCatchStmts, Finally);
}

StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
if (Throw) {
ExprResult Result = DefaultLvalueConversion(Throw);
if (Result.isInvalid())
return StmtError();

Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false);
if (Result.isInvalid())
return StmtError();
Throw = Result.get();

QualType ThrowType = Throw->getType();
// Make sure the expression type is an ObjC pointer or "void *".
if (!ThrowType->isDependentType() &&
!ThrowType->isObjCObjectPointerType()) {
const PointerType *PT = ThrowType->getAs<PointerType>();
if (!PT || !PT->getPointeeType()->isVoidType())
return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object)
<< Throw->getType() << Throw->getSourceRange());
}
}

return new (Context) ObjCAtThrowStmt(AtLoc, Throw);
}

StmtResult
Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
Scope *CurScope) {
if (!getLangOpts().ObjCExceptions)
Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw";

if (!Throw) {
// @throw without an expression designates a rethrow (which must occur
// in the context of an @catch clause).
Scope *AtCatchParent = CurScope;
while (AtCatchParent && !AtCatchParent->isAtCatchScope())
AtCatchParent = AtCatchParent->getParent();
if (!AtCatchParent)
return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch));
}
return BuildObjCAtThrowStmt(AtLoc, Throw);
}

ExprResult
Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) {
ExprResult result = DefaultLvalueConversion(operand);
if (result.isInvalid())
return ExprError();
operand = result.get();

// Make sure the expression type is an ObjC pointer or "void *".
QualType type = operand->getType();
if (!type->isDependentType() &&
!type->isObjCObjectPointerType()) {
const PointerType *pointerType = type->getAs<PointerType>();
if (!pointerType || !pointerType->getPointeeType()->isVoidType()) {
if (getLangOpts().CPlusPlus) {
if (RequireCompleteType(atLoc, type,
diag::err_incomplete_receiver_type))
return Diag(atLoc, diag::err_objc_synchronized_expects_object)
<< type << operand->getSourceRange();

ExprResult result = PerformContextuallyConvertToObjCPointer(operand);
if (result.isInvalid())
return ExprError();
if (!result.isUsable())
return Diag(atLoc, diag::err_objc_synchronized_expects_object)
<< type << operand->getSourceRange();

operand = result.get();
} else {
return Diag(atLoc, diag::err_objc_synchronized_expects_object)
<< type << operand->getSourceRange();
}
}
}

// The operand to @synchronized is a full-expression.
return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false);
}

StmtResult
Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
Stmt *SyncBody) {
// We can't jump into or indirect-jump out of a @synchronized block.
setFunctionHasBranchProtectedScope();
return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);
}

/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block
/// and creates a proper catch handler from them.
StmtResult
Expand All @@ -4435,12 +4142,6 @@ Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
CXXCatchStmt(CatchLoc, cast_or_null<VarDecl>(ExDecl), HandlerBlock);
}

StmtResult
Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
setFunctionHasBranchProtectedScope();
return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
}

namespace {
class CatchHandlerType {
QualType QT;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/SemaStmtAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,11 @@ ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A,
}

auto *Assumption = A.getArgAsExpr(0);

if (DiagnoseUnexpandedParameterPack(Assumption)) {
return ExprError();
}

if (Assumption->getDependence() == ExprDependence::None) {
ExprResult Res = BuildCXXAssumeExpr(Assumption, A.getAttrName(), Range);
if (Res.isInvalid())
Expand Down
14 changes: 10 additions & 4 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6556,7 +6556,8 @@ bool Sema::CheckTemplateArgumentList(
TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
SmallVectorImpl<TemplateArgument> &SugaredConverted,
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) {
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied,
bool PartialOrderingTTP) {

if (ConstraintsNotSatisfied)
*ConstraintsNotSatisfied = false;
Expand Down Expand Up @@ -6627,9 +6628,14 @@ bool Sema::CheckTemplateArgumentList(
bool PackExpansionIntoNonPack =
NewArgs[ArgIdx].getArgument().isPackExpansion() &&
(!(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param));
if (PackExpansionIntoNonPack && (isa<TypeAliasTemplateDecl>(Template) ||
isa<ConceptDecl>(Template))) {
// Core issue 1430: we have a pack expansion as an argument to an
// CWG1430: Don't diagnose this pack expansion when partial
// ordering template template parameters. Some uses of the template could
// be valid, and invalid uses will be diagnosed later during
// instantiation.
if (PackExpansionIntoNonPack && !PartialOrderingTTP &&
(isa<TypeAliasTemplateDecl>(Template) ||
isa<ConceptDecl>(Template))) {
// CWG1430: we have a pack expansion as an argument to an
// alias template, and it's not part of a parameter pack. This
// can't be canonicalized, so reject it now.
// As for concepts - we cannot normalize constraints where this
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6243,7 +6243,9 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
// specialized as A.
SmallVector<TemplateArgument, 4> SugaredPArgs;
if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, SugaredPArgs,
PArgs) ||
PArgs, /*UpdateArgsWithConversions=*/true,
/*ConstraintsNotSatisfied=*/nullptr,
/*PartialOrderTTP=*/true) ||
Trap.hasErrorOccurred())
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
Expand Down Expand Up @@ -1217,7 +1218,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,

// In ARC, infer 'retaining' for variables of retainable type.
if (SemaRef.getLangOpts().ObjCAutoRefCount &&
SemaRef.inferObjCARCLifetime(Var))
SemaRef.ObjC().inferObjCARCLifetime(Var))
Var->setInvalidDecl();

if (SemaRef.getLangOpts().OpenCL)
Expand Down
465 changes: 5 additions & 460 deletions clang/lib/Sema/SemaType.cpp

Large diffs are not rendered by default.

133 changes: 72 additions & 61 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenACC.h"
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaSYCL.h"
Expand Down Expand Up @@ -1609,8 +1610,8 @@ class TreeTransform {
Stmt *TryBody,
MultiStmtArg CatchStmts,
Stmt *Finally) {
return getSema().ActOnObjCAtTryStmt(AtLoc, TryBody, CatchStmts,
Finally);
return getSema().ObjC().ActOnObjCAtTryStmt(AtLoc, TryBody, CatchStmts,
Finally);
}

/// Rebuild an Objective-C exception declaration.
Expand All @@ -1619,10 +1620,9 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TInfo, QualType T) {
return getSema().BuildObjCExceptionDecl(TInfo, T,
ExceptionDecl->getInnerLocStart(),
ExceptionDecl->getLocation(),
ExceptionDecl->getIdentifier());
return getSema().ObjC().BuildObjCExceptionDecl(
TInfo, T, ExceptionDecl->getInnerLocStart(),
ExceptionDecl->getLocation(), ExceptionDecl->getIdentifier());
}

/// Build a new Objective-C \@catch statement.
Expand All @@ -1633,8 +1633,7 @@ class TreeTransform {
SourceLocation RParenLoc,
VarDecl *Var,
Stmt *Body) {
return getSema().ActOnObjCAtCatchStmt(AtLoc, RParenLoc,
Var, Body);
return getSema().ObjC().ActOnObjCAtCatchStmt(AtLoc, RParenLoc, Var, Body);
}

/// Build a new Objective-C \@finally statement.
Expand All @@ -1643,7 +1642,7 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildObjCAtFinallyStmt(SourceLocation AtLoc,
Stmt *Body) {
return getSema().ActOnObjCAtFinallyStmt(AtLoc, Body);
return getSema().ObjC().ActOnObjCAtFinallyStmt(AtLoc, Body);
}

/// Build a new Objective-C \@throw statement.
Expand All @@ -1652,7 +1651,7 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildObjCAtThrowStmt(SourceLocation AtLoc,
Expr *Operand) {
return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
return getSema().ObjC().BuildObjCAtThrowStmt(AtLoc, Operand);
}

/// Build a new OpenMP Canonical loop.
Expand Down Expand Up @@ -2492,7 +2491,7 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildObjCAtSynchronizedOperand(SourceLocation atLoc,
Expr *object) {
return getSema().ActOnObjCAtSynchronizedOperand(atLoc, object);
return getSema().ObjC().ActOnObjCAtSynchronizedOperand(atLoc, object);
}

/// Build a new Objective-C \@synchronized statement.
Expand All @@ -2501,7 +2500,7 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildObjCAtSynchronizedStmt(SourceLocation AtLoc,
Expr *Object, Stmt *Body) {
return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, Object, Body);
return getSema().ObjC().ActOnObjCAtSynchronizedStmt(AtLoc, Object, Body);
}

/// Build a new Objective-C \@autoreleasepool statement.
Expand All @@ -2510,7 +2509,7 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildObjCAutoreleasePoolStmt(SourceLocation AtLoc,
Stmt *Body) {
return getSema().ActOnObjCAutoreleasePoolStmt(AtLoc, Body);
return getSema().ObjC().ActOnObjCAutoreleasePoolStmt(AtLoc, Body);
}

/// Build a new Objective-C fast enumeration statement.
Expand All @@ -2522,14 +2521,13 @@ class TreeTransform {
Expr *Collection,
SourceLocation RParenLoc,
Stmt *Body) {
StmtResult ForEachStmt = getSema().ActOnObjCForCollectionStmt(ForLoc,
Element,
Collection,
RParenLoc);
StmtResult ForEachStmt = getSema().ObjC().ActOnObjCForCollectionStmt(
ForLoc, Element, Collection, RParenLoc);
if (ForEachStmt.isInvalid())
return StmtError();

return getSema().FinishObjCForCollectionStmt(ForEachStmt.get(), Body);
return getSema().ObjC().FinishObjCForCollectionStmt(ForEachStmt.get(),
Body);
}

/// Build a new C++ exception declaration.
Expand Down Expand Up @@ -2595,8 +2593,8 @@ class TreeTransform {
diag::err_objc_for_range_init_stmt)
<< Init->getSourceRange();
}
return getSema().ActOnObjCForCollectionStmt(ForLoc, LoopVar,
RangeExpr, RParenLoc);
return getSema().ObjC().ActOnObjCForCollectionStmt(
ForLoc, LoopVar, RangeExpr, RParenLoc);
}
}
}
Expand Down Expand Up @@ -3720,7 +3718,7 @@ class TreeTransform {
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
return getSema().BuildObjCBoxedExpr(SR, ValueExpr);
return getSema().ObjC().BuildObjCBoxedExpr(SR, ValueExpr);
}

/// Build a new Objective-C array literal.
Expand All @@ -3729,16 +3727,16 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildObjCArrayLiteral(SourceRange Range,
Expr **Elements, unsigned NumElements) {
return getSema().BuildObjCArrayLiteral(Range,
MultiExprArg(Elements, NumElements));
return getSema().ObjC().BuildObjCArrayLiteral(
Range, MultiExprArg(Elements, NumElements));
}

ExprResult RebuildObjCSubscriptRefExpr(SourceLocation RB,
Expr *Base, Expr *Key,
ObjCMethodDecl *getterMethod,
ObjCMethodDecl *setterMethod) {
return getSema().BuildObjCSubscriptExpression(RB, Base, Key,
getterMethod, setterMethod);
return getSema().ObjC().BuildObjCSubscriptExpression(
RB, Base, Key, getterMethod, setterMethod);
}

/// Build a new Objective-C dictionary literal.
Expand All @@ -3747,7 +3745,7 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildObjCDictionaryLiteral(SourceRange Range,
MutableArrayRef<ObjCDictionaryElement> Elements) {
return getSema().BuildObjCDictionaryLiteral(Range, Elements);
return getSema().ObjC().BuildObjCDictionaryLiteral(Range, Elements);
}

/// Build a new Objective-C \@encode expression.
Expand All @@ -3757,7 +3755,8 @@ class TreeTransform {
ExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc,
TypeSourceInfo *EncodeTypeInfo,
SourceLocation RParenLoc) {
return SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo, RParenLoc);
return SemaRef.ObjC().BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo,
RParenLoc);
}

/// Build a new Objective-C class message.
Expand All @@ -3768,11 +3767,10 @@ class TreeTransform {
SourceLocation LBracLoc,
MultiExprArg Args,
SourceLocation RBracLoc) {
return SemaRef.BuildClassMessage(ReceiverTypeInfo,
ReceiverTypeInfo->getType(),
/*SuperLoc=*/SourceLocation(),
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args);
return SemaRef.ObjC().BuildClassMessage(
ReceiverTypeInfo, ReceiverTypeInfo->getType(),
/*SuperLoc=*/SourceLocation(), Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args);
}

/// Build a new Objective-C instance message.
Expand All @@ -3783,11 +3781,10 @@ class TreeTransform {
SourceLocation LBracLoc,
MultiExprArg Args,
SourceLocation RBracLoc) {
return SemaRef.BuildInstanceMessage(Receiver,
Receiver->getType(),
/*SuperLoc=*/SourceLocation(),
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args);
return SemaRef.ObjC().BuildInstanceMessage(Receiver, Receiver->getType(),
/*SuperLoc=*/SourceLocation(),
Sel, Method, LBracLoc,
SelectorLocs, RBracLoc, Args);
}

/// Build a new Objective-C instance/class message to 'super'.
Expand All @@ -3799,18 +3796,13 @@ class TreeTransform {
SourceLocation LBracLoc,
MultiExprArg Args,
SourceLocation RBracLoc) {
return Method->isInstanceMethod() ? SemaRef.BuildInstanceMessage(nullptr,
SuperType,
SuperLoc,
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args)
: SemaRef.BuildClassMessage(nullptr,
SuperType,
SuperLoc,
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args);


return Method->isInstanceMethod()
? SemaRef.ObjC().BuildInstanceMessage(
nullptr, SuperType, SuperLoc, Sel, Method, LBracLoc,
SelectorLocs, RBracLoc, Args)
: SemaRef.ObjC().BuildClassMessage(nullptr, SuperType, SuperLoc,
Sel, Method, LBracLoc,
SelectorLocs, RBracLoc, Args);
}

/// Build a new Objective-C ivar reference expression.
Expand Down Expand Up @@ -7964,6 +7956,11 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
// Transform the "then" branch.
StmtResult Then;
if (!ConstexprConditionValue || *ConstexprConditionValue) {
EnterExpressionEvaluationContext Ctx(
getSema(), Sema::ExpressionEvaluationContext::ImmediateFunctionContext,
nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other,
S->isNonNegatedConsteval());

Then = getDerived().TransformStmt(S->getThen());
if (Then.isInvalid())
return StmtError();
Expand All @@ -7978,6 +7975,11 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
// Transform the "else" branch.
StmtResult Else;
if (!ConstexprConditionValue || !*ConstexprConditionValue) {
EnterExpressionEvaluationContext Ctx(
getSema(), Sema::ExpressionEvaluationContext::ImmediateFunctionContext,
nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other,
S->isNegatedConsteval());

Else = getDerived().TransformStmt(S->getElse());
if (Else.isInvalid())
return StmtError();
Expand Down Expand Up @@ -11470,6 +11472,16 @@ void OpenACCClauseTransform<Derived>::VisitWaitClause(
ParsedClause.getQueuesLoc(), ParsedClause.getQueueIdExprs(),
ParsedClause.getEndLoc());
}

template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitDeviceTypeClause(
const OpenACCDeviceTypeClause &C) {
// Nothing to transform here, just create a new version of 'C'.
NewClause = OpenACCDeviceTypeClause::Create(
Self.getSema().getASTContext(), C.getClauseKind(),
ParsedClause.getBeginLoc(), ParsedClause.getLParenLoc(),
C.getArchitectures(), ParsedClause.getEndLoc());
}
} // namespace
template <typename Derived>
OpenACCClause *TreeTransform<Derived>::TransformOpenACCClause(
Expand Down Expand Up @@ -15430,9 +15442,9 @@ TransformObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
Result.get() == E->getSubExpr())
return E;

return SemaRef.BuildObjCBridgedCast(E->getLParenLoc(), E->getBridgeKind(),
E->getBridgeKeywordLoc(), TSInfo,
Result.get());
return SemaRef.ObjC().BuildObjCBridgedCast(
E->getLParenLoc(), E->getBridgeKind(), E->getBridgeKeywordLoc(), TSInfo,
Result.get());
}

template <typename Derived>
Expand Down Expand Up @@ -15820,10 +15832,9 @@ QualType TreeTransform<Derived>::RebuildObjCTypeParamType(
ArrayRef<ObjCProtocolDecl *> Protocols,
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc) {
return SemaRef.BuildObjCTypeParamType(Decl,
ProtocolLAngleLoc, Protocols,
ProtocolLocs, ProtocolRAngleLoc,
/*FailOnError=*/true);
return SemaRef.ObjC().BuildObjCTypeParamType(
Decl, ProtocolLAngleLoc, Protocols, ProtocolLocs, ProtocolRAngleLoc,
/*FailOnError=*/true);
}

template<typename Derived>
Expand All @@ -15837,11 +15848,11 @@ QualType TreeTransform<Derived>::RebuildObjCObjectType(
ArrayRef<ObjCProtocolDecl *> Protocols,
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc) {
return SemaRef.BuildObjCObjectType(BaseType, Loc, TypeArgsLAngleLoc, TypeArgs,
TypeArgsRAngleLoc, ProtocolLAngleLoc,
Protocols, ProtocolLocs, ProtocolRAngleLoc,
/*FailOnError=*/true,
/*Rebuilding=*/true);
return SemaRef.ObjC().BuildObjCObjectType(
BaseType, Loc, TypeArgsLAngleLoc, TypeArgs, TypeArgsRAngleLoc,
ProtocolLAngleLoc, Protocols, ProtocolLocs, ProtocolRAngleLoc,
/*FailOnError=*/true,
/*Rebuilding=*/true);
}

template<typename Derived>
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) {

// FIXME: These are defined in one place, but properties in class extensions
// end up being back-patched into the main interface. See
// Sema::HandlePropertyInClassExtension for the offending code.
// SemaObjC::HandlePropertyInClassExtension for the offending code.
case Decl::ObjCInterface:
return nullptr;

Expand Down
32 changes: 24 additions & 8 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/Weak.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTDeserializationListener.h"
Expand Down Expand Up @@ -4233,9 +4234,9 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
/// Move the given method to the back of the global list of methods.
static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) {
// Find the entry for this selector in the method pool.
Sema::GlobalMethodPool::iterator Known
= S.MethodPool.find(Method->getSelector());
if (Known == S.MethodPool.end())
SemaObjC::GlobalMethodPool::iterator Known =
S.ObjC().MethodPool.find(Method->getSelector());
if (Known == S.ObjC().MethodPool.end())
return;

// Retrieve the appropriate method list.
Expand Down Expand Up @@ -8551,7 +8552,7 @@ namespace serialization {
static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
ObjCMethodList &List) {
for (ObjCMethodDecl *M : llvm::reverse(Methods))
S.addMethodToGlobalList(&List, M);
S.ObjC().addMethodToGlobalList(&List, M);
}

void ASTReader::ReadMethodPool(Selector Sel) {
Expand All @@ -8576,8 +8577,10 @@ void ASTReader::ReadMethodPool(Selector Sel) {
return;

Sema &S = *getSema();
Sema::GlobalMethodPool::iterator Pos =
S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethodPool::Lists()))
SemaObjC::GlobalMethodPool::iterator Pos =
S.ObjC()
.MethodPool
.insert(std::make_pair(Sel, SemaObjC::GlobalMethodPool::Lists()))
.first;

Pos->second.first.setBits(Visitor.getInstanceBits());
Expand Down Expand Up @@ -11905,6 +11908,21 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
DevNumExpr, QueuesLoc, QueueIdExprs,
EndLoc);
}
case OpenACCClauseKind::DeviceType:
case OpenACCClauseKind::DType: {
SourceLocation LParenLoc = readSourceLocation();
llvm::SmallVector<DeviceTypeArgument> Archs;
unsigned NumArchs = readInt();

for (unsigned I = 0; I < NumArchs; ++I) {
IdentifierInfo *Ident = readBool() ? readIdentifier() : nullptr;
SourceLocation Loc = readSourceLocation();
Archs.emplace_back(Ident, Loc);
}

return OpenACCDeviceTypeClause::Create(getContext(), ClauseKind, BeginLoc,
LParenLoc, Archs, EndLoc);
}

case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
Expand All @@ -11926,8 +11944,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
case OpenACCClauseKind::Bind:
case OpenACCClauseKind::DeviceNum:
case OpenACCClauseKind::DefaultAsync:
case OpenACCClauseKind::DeviceType:
case OpenACCClauseKind::DType:
case OpenACCClauseKind::Tile:
case OpenACCClauseKind::Gang:
case OpenACCClauseKind::Invalid:
Expand Down
29 changes: 21 additions & 8 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/Weak.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
Expand Down Expand Up @@ -3547,7 +3548,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
using namespace llvm;

// Do we have to do anything at all?
if (SemaRef.MethodPool.empty() && SelectorIDs.empty())
if (SemaRef.ObjC().MethodPool.empty() && SelectorIDs.empty())
return;
unsigned NumTableEntries = 0;
// Create and write out the blob that contains selectors and the method pool.
Expand All @@ -3561,13 +3562,14 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
for (auto &SelectorAndID : SelectorIDs) {
Selector S = SelectorAndID.first;
SelectorID ID = SelectorAndID.second;
Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S);
SemaObjC::GlobalMethodPool::iterator F =
SemaRef.ObjC().MethodPool.find(S);
ASTMethodPoolTrait::data_type Data = {
ID,
ObjCMethodList(),
ObjCMethodList()
};
if (F != SemaRef.MethodPool.end()) {
if (F != SemaRef.ObjC().MethodPool.end()) {
Data.Instance = F->second.first;
Data.Factory = F->second.second;
}
Expand Down Expand Up @@ -3652,7 +3654,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
using namespace llvm;

if (SemaRef.ReferencedSelectors.empty())
if (SemaRef.ObjC().ReferencedSelectors.empty())
return;

RecordData Record;
Expand All @@ -3661,7 +3663,7 @@ void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
// Note: this writes out all references even for a dependent AST. But it is
// very tricky to fix, and given that @selector shouldn't really appear in
// headers, probably not worth it. It's not a correctness issue.
for (auto &SelectorAndLocation : SemaRef.ReferencedSelectors) {
for (auto &SelectorAndLocation : SemaRef.ObjC().ReferencedSelectors) {
Selector Sel = SelectorAndLocation.first;
SourceLocation Loc = SelectorAndLocation.second;
Writer.AddSelectorRef(Sel);
Expand Down Expand Up @@ -5346,7 +5348,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
for (auto &SelectorAndID : SelectorIDs)
AllSelectors.push_back(SelectorAndID.first);
for (auto &Selector : AllSelectors)
SemaRef.updateOutOfDateSelector(Selector);
SemaRef.ObjC().updateOutOfDateSelector(Selector);

// Form the record of special types.
RecordData SpecialTypes;
Expand Down Expand Up @@ -7933,6 +7935,19 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
writeOpenACCIntExprList(WC->getQueueIdExprs());
return;
}
case OpenACCClauseKind::DeviceType:
case OpenACCClauseKind::DType: {
const auto *DTC = cast<OpenACCDeviceTypeClause>(C);
writeSourceLocation(DTC->getLParenLoc());
writeUInt32(DTC->getArchitectures().size());
for (const DeviceTypeArgument &Arg : DTC->getArchitectures()) {
writeBool(Arg.first);
if (Arg.first)
AddIdentifierRef(Arg.first);
writeSourceLocation(Arg.second);
}
return;
}

case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
Expand All @@ -7954,8 +7969,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
case OpenACCClauseKind::Bind:
case OpenACCClauseKind::DeviceNum:
case OpenACCClauseKind::DefaultAsync:
case OpenACCClauseKind::DeviceType:
case OpenACCClauseKind::DType:
case OpenACCClauseKind::Tile:
case OpenACCClauseKind::Gang:
case OpenACCClauseKind::Invalid:
Expand Down
15 changes: 14 additions & 1 deletion clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ class DereferenceChecker
: public Checker< check::Location,
check::Bind,
EventDispatcher<ImplicitNullDerefEvent> > {
enum DerefKind { NullPointer, UndefinedPointerValue };
enum DerefKind { NullPointer, UndefinedPointerValue, AddressOfLabel };

BugType BT_Null{this, "Dereference of null pointer", categories::LogicError};
BugType BT_Undef{this, "Dereference of undefined pointer value",
categories::LogicError};
BugType BT_Label{this, "Dereference of the address of a label",
categories::LogicError};

void reportBug(DerefKind K, ProgramStateRef State, const Stmt *S,
CheckerContext &C) const;
Expand Down Expand Up @@ -167,6 +169,11 @@ void DereferenceChecker::reportBug(DerefKind K, ProgramStateRef State,
DerefStr1 = " results in an undefined pointer dereference";
DerefStr2 = " results in a dereference of an undefined pointer value";
break;
case DerefKind::AddressOfLabel:
BT = &BT_Label;
DerefStr1 = " results in an undefined pointer dereference";
DerefStr2 = " results in a dereference of an address of a label";
break;
};

// Generate an error node.
Expand Down Expand Up @@ -287,6 +294,12 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
if (V.isUndef())
return;

// One should never write to label addresses.
if (auto Label = L.getAs<loc::GotoLabel>()) {
reportBug(DerefKind::AddressOfLabel, C.getState(), S, C);
return;
}

const MemRegion *MR = L.getAsRegion();
const TypedValueRegion *TVR = dyn_cast_or_null<TypedValueRegion>(MR);
if (!TVR)
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
// Pointer arithmetic: '*(x + 2)' -> 'x') etc.
if (const Expr *Inner = peelOffPointerArithmetic(B)) {
E = Inner;
} else if (B->isAssignmentOp()) {
// Follow LHS of assignments: '*p = 404' -> 'p'.
E = B->getLHS();
} else {
// Probably more arithmetic can be pattern-matched here,
// but for now give up.
Expand Down
10 changes: 10 additions & 0 deletions clang/test/AST/Interp/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,16 @@ namespace LocalVLA {
// both-note@-4 {{function parameter 'size' with unknown value}}
#endif
}

void f (unsigned int m) {
int e[2][m];
#if __cplusplus >= 202002L
// both-note@-3 {{declared here}}
// both-warning@-3 2{{variable length array}}
// both-note@-4 {{function parameter 'm' with unknown value}}
#endif
e[0][0] = 0;
}
}

char melchizedek[2];
Expand Down
23 changes: 23 additions & 0 deletions clang/test/AST/ast-print-openacc-compute-construct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,28 @@ void foo() {
// CHECK: #pragma acc parallel wait(devnum: i : queues: *iPtr, i)
#pragma acc parallel wait(devnum:i:queues:*iPtr, i)
while(true);

bool SomeB;
struct SomeStruct{} SomeStructImpl;

//#pragma acc parallel dtype(SomeB)
#pragma acc parallel dtype(SomeB)
while(true);

//#pragma acc parallel device_type(SomeStruct)
#pragma acc parallel device_type(SomeStruct)
while(true);

//#pragma acc parallel device_type(int)
#pragma acc parallel device_type(int)
while(true);

//#pragma acc parallel dtype(bool)
#pragma acc parallel dtype(bool)
while(true);

//#pragma acc parallel device_type (SomeStructImpl)
#pragma acc parallel device_type (SomeStructImpl)
while(true);
}

15 changes: 7 additions & 8 deletions clang/test/Analysis/gh-issue-89185.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-output text -verify %s

void clang_analyzer_dump(char);
void clang_analyzer_dump_ptr(char*);
void clang_analyzer_warnIfReached(void);

// https://github.com/llvm/llvm-project/issues/89185
void binding_to_label_loc() {
char *b = &&MyLabel;
char *b = &&MyLabel; // expected-note {{'b' initialized here}}
MyLabel:
*b = 0; // no-crash
clang_analyzer_dump_ptr(b); // expected-warning {{&&MyLabel}}
clang_analyzer_dump(*b); // expected-warning {{Unknown}}
// FIXME: We should never reach here, as storing to a label is invalid.
*b = 0;
// expected-warning@-1 {{Dereference of the address of a label}}
// expected-note@-2 {{Dereference of the address of a label}}
clang_analyzer_warnIfReached(); // no-warning: Unreachable due to fatal error.
}
27 changes: 27 additions & 0 deletions clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,16 +539,43 @@ namespace N4 {
a->y;
a->f();
a->g();

a->T::x;
a->T::y;
a->T::f();
a->T::g();

// FIXME: 'U' should be a dependent name, and its lookup context should be 'a.operator->()'!
a->U::x; // expected-error {{use of undeclared identifier 'U'}}
a->U::y; // expected-error {{use of undeclared identifier 'U'}}
a->U::f(); // expected-error {{use of undeclared identifier 'U'}}
a->U::g(); // expected-error {{use of undeclared identifier 'U'}}
}

void instantiated(D a) {
a->x;
a->y; // expected-error {{no member named 'y' in 'N4::B'}}
a->f();
a->g(); // expected-error {{no member named 'g' in 'N4::B'}}

a->T::x;
a->T::y; // expected-error {{no member named 'y' in 'N4::B'}}
a->T::f();
a->T::g(); // expected-error {{no member named 'g' in 'N4::B'}}
}
};

template void D<B>::instantiated(D); // expected-note {{in instantiation of}}

template<typename T>
struct Typo {
T *operator->();

void not_instantiated(Typo a) {
a->Not_instantiated;
a->typo;
a->T::Not_instantiated;
a->T::typo;
}
};
} // namespace N4
6 changes: 3 additions & 3 deletions clang/test/Driver/frelaxed-template-template-args.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang -fsyntax-only -### %s 2>&1 | FileCheck --check-prefix=CHECK-DEF %s
// RUN: %clang -fsyntax-only -frelaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-ON --allow-empty %s
// RUN: %clang -fsyntax-only -frelaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-ON %s
// RUN: %clang -fsyntax-only -fno-relaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-OFF %s

// CHECK-DEF: "-cc1"{{.*}} "-fno-relaxed-template-template-args"
// CHECK-ON-NOT: warning: argument '-frelaxed-template-template-args' is deprecated [-Wdeprecated]
// CHECK-DEF-NOT: "-cc1"{{.*}} "-fno-relaxed-template-template-args"
// CHECK-ON: warning: argument '-frelaxed-template-template-args' is deprecated [-Wdeprecated]
// CHECK-OFF: warning: argument '-fno-relaxed-template-template-args' is deprecated [-Wdeprecated]
6 changes: 3 additions & 3 deletions clang/test/Driver/rewrite-legacy-objc.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
// TEST0: "-cc1"
// TEST0: "-rewrite-objc"
// FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead.
// TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fno-relaxed-template-template-args" "-fmax-type-align=16"
// TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16"
// TEST0: rewrite-legacy-objc.m"
// RUN: %clang --target=i386-apple-macosx10.9.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \
// RUN: FileCheck -check-prefix=TEST1 %s
// RUN: %clang --target=i386-apple-macosx10.6.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \
// RUN: FileCheck -check-prefix=TEST2 %s
// TEST1: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fno-relaxed-template-template-args" "-fmax-type-align=16"
// TEST2: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fno-relaxed-template-template-args" "-fmax-type-align=16"
// TEST1: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16"
// TEST2: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16"
2 changes: 1 addition & 1 deletion clang/test/Driver/rewrite-objc.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
// RUN: FileCheck -check-prefix=TEST0 %s
// TEST0: "-cc1" {{.*}} "-rewrite-objc"
// FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead.
// TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fno-relaxed-template-template-args" "-fmax-type-align=16"
// TEST0: "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fgnuc-version=4.2.1"{{.*}} "-fobjc-runtime=macosx" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16"
58 changes: 58 additions & 0 deletions clang/test/OpenMP/target_ast_print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,64 @@ foo();
}
#endif // OMP52

#ifdef OMP60

///==========================================================================///
// RUN: %clang_cc1 -DOMP60 -verify -Wno-vla -fopenmp -fopenmp-version=60 -ast-print %s | FileCheck %s --check-prefix OMP60
// RUN: %clang_cc1 -DOMP60 -fopenmp -fopenmp-version=60 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -DOMP60 -fopenmp -fopenmp-version=60 -std=c++11 -include-pch %t -verify -Wno-vla %s -ast-print | FileCheck %s --check-prefix OMP60

// RUN: %clang_cc1 -DOMP60 -verify -Wno-vla -fopenmp-simd -fopenmp-version=60 -ast-print %s | FileCheck %s --check-prefix OMP60
// RUN: %clang_cc1 -DOMP60 -fopenmp-simd -fopenmp-version=60 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -DOMP60 -fopenmp-simd -fopenmp-version=60 -std=c++11 -include-pch %t -verify -Wno-vla %s -ast-print | FileCheck %s --check-prefix OMP60

void foo() {}
template <typename T, int C>
T tmain(T argc, T *argv) {
T i;
#pragma omp target map(from always: i)
foo();
#pragma omp target map(from, close: i)
foo();
#pragma omp target map(always,close: i)
foo();
return 0;
}
//OMP60: template <typename T, int C> T tmain(T argc, T *argv) {
//OMP60-NEXT: T i;
//OMP60-NEXT: #pragma omp target map(always,from: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: #pragma omp target map(close,from: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: #pragma omp target map(always,close,tofrom: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: return 0;
//OMP60-NEXT:}
//OMP60: template<> int tmain<int, 5>(int argc, int *argv) {
//OMP60-NEXT: int i;
//OMP60-NEXT: #pragma omp target map(always,from: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: #pragma omp target map(close,from: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: #pragma omp target map(always,close,tofrom: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: return 0;
//OMP60-NEXT:}
//OMP60: template<> char tmain<char, 1>(char argc, char *argv) {
//OMP60-NEXT: char i;
//OMP60-NEXT: #pragma omp target map(always,from: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: #pragma omp target map(close,from: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: #pragma omp target map(always,close,tofrom: i)
//OMP60-NEXT: foo();
//OMP60-NEXT: return 0;
//OMP60-NEXT:}
int main (int argc, char **argv) {
return tmain<int, 5>(argc, &argc) + tmain<char, 1>(argv[0][0], argv[0]);
}
#endif // OMP60

#ifdef OMPX

// RUN: %clang_cc1 -DOMPX -verify -Wno-vla -fopenmp -fopenmp-extensions -ast-print %s | FileCheck %s --check-prefix=OMPX
Expand Down
Loading