summaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
commit45b533945f0851ec234ca846e1af5ee1e4df0b6e (patch)
tree0a5b74c0b9ca73aded34df95c91fcaf3815230d8 /lib/Sema
parent7e86edd64bfae4e324224452e4ea879b3371a4bd (diff)
downloadsrc-test2-45b533945f0851ec234ca846e1af5ee1e4df0b6e.tar.gz
src-test2-45b533945f0851ec234ca846e1af5ee1e4df0b6e.zip
Notes
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp184
-rw-r--r--lib/Sema/AttributeList.cpp31
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/DeclSpec.cpp120
-rw-r--r--lib/Sema/JumpDiagnostics.cpp7
-rw-r--r--lib/Sema/MultiplexExternalSemaSource.cpp12
-rw-r--r--lib/Sema/ScopeInfo.cpp4
-rw-r--r--lib/Sema/Sema.cpp84
-rw-r--r--lib/Sema/SemaAccess.cpp13
-rw-r--r--lib/Sema/SemaCUDA.cpp144
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp24
-rw-r--r--lib/Sema/SemaCast.cpp110
-rw-r--r--lib/Sema/SemaChecking.cpp423
-rw-r--r--lib/Sema/SemaCodeComplete.cpp49
-rw-r--r--lib/Sema/SemaCoroutine.cpp448
-rw-r--r--lib/Sema/SemaDecl.cpp1228
-rw-r--r--lib/Sema/SemaDeclAttr.cpp695
-rw-r--r--lib/Sema/SemaDeclCXX.cpp593
-rw-r--r--lib/Sema/SemaDeclObjC.cpp172
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp68
-rw-r--r--lib/Sema/SemaExpr.cpp948
-rw-r--r--lib/Sema/SemaExprCXX.cpp226
-rw-r--r--lib/Sema/SemaExprMember.cpp83
-rw-r--r--lib/Sema/SemaExprObjC.cpp262
-rw-r--r--lib/Sema/SemaFixItUtils.cpp6
-rw-r--r--lib/Sema/SemaInit.cpp76
-rw-r--r--lib/Sema/SemaLambda.cpp115
-rw-r--r--lib/Sema/SemaLookup.cpp329
-rw-r--r--lib/Sema/SemaObjCProperty.cpp743
-rw-r--r--lib/Sema/SemaOpenMP.cpp2746
-rw-r--r--lib/Sema/SemaOverload.cpp810
-rw-r--r--lib/Sema/SemaPseudoObject.cpp323
-rw-r--r--lib/Sema/SemaStmt.cpp191
-rw-r--r--lib/Sema/SemaStmtAsm.cpp224
-rw-r--r--lib/Sema/SemaStmtAttr.cpp75
-rw-r--r--lib/Sema/SemaTemplate.cpp200
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp129
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp45
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp57
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp5
-rw-r--r--lib/Sema/SemaType.cpp630
-rw-r--r--lib/Sema/TreeTransform.h732
42 files changed, 9393 insertions, 3972 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index f2ff48ad69f4..5f74343fbd95 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -34,7 +34,6 @@
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
@@ -99,7 +98,7 @@ namespace {
}
}
};
-}
+} // anonymous namespace
/// CheckUnreachable - Check for unreachable code.
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
@@ -157,12 +156,45 @@ public:
<< DiagRange << isAlwaysTrue;
}
};
-} // namespace
+} // anonymous namespace
//===----------------------------------------------------------------------===//
// Check for infinite self-recursion in functions
//===----------------------------------------------------------------------===//
+// Returns true if the function is called anywhere within the CFGBlock.
+// For member functions, the additional condition of being call from the
+// this pointer is required.
+static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {
+ // Process all the Stmt's in this block to find any calls to FD.
+ for (const auto &B : Block) {
+ if (B.getKind() != CFGElement::Statement)
+ continue;
+
+ const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
+ if (!CE || !CE->getCalleeDecl() ||
+ CE->getCalleeDecl()->getCanonicalDecl() != FD)
+ continue;
+
+ // Skip function calls which are qualified with a templated class.
+ if (const DeclRefExpr *DRE =
+ dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) {
+ if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
+ if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
+ isa<TemplateSpecializationType>(NNS->getAsType())) {
+ continue;
+ }
+ }
+ }
+
+ const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE);
+ if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
+ !MCE->getMethodDecl()->isVirtual())
+ return true;
+ }
+ return false;
+}
+
// All blocks are in one of three states. States are ordered so that blocks
// can only move to higher states.
enum RecursiveState {
@@ -171,68 +203,56 @@ enum RecursiveState {
FoundPathWithNoRecursiveCall
};
-static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
- CFGBlock &Block, unsigned ExitID,
- llvm::SmallVectorImpl<RecursiveState> &States,
- RecursiveState State) {
- unsigned ID = Block.getBlockID();
+// Returns true if there exists a path to the exit block and every path
+// to the exit block passes through a call to FD.
+static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
- // A block's state can only move to a higher state.
- if (States[ID] >= State)
- return;
+ const unsigned ExitID = cfg->getExit().getBlockID();
- States[ID] = State;
+ // Mark all nodes as FoundNoPath, then set the status of the entry block.
+ SmallVector<RecursiveState, 16> States(cfg->getNumBlockIDs(), FoundNoPath);
+ States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall;
- // Found a path to the exit node without a recursive call.
- if (ID == ExitID && State == FoundPathWithNoRecursiveCall)
- return;
+ // Make the processing stack and seed it with the entry block.
+ SmallVector<CFGBlock *, 16> Stack;
+ Stack.push_back(&cfg->getEntry());
- if (State == FoundPathWithNoRecursiveCall) {
- // If the current state is FoundPathWithNoRecursiveCall, the successors
- // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine
- // which, process all the Stmt's in this block to find any recursive calls.
- for (const auto &B : Block) {
- if (B.getKind() != CFGElement::Statement)
- continue;
+ while (!Stack.empty()) {
+ CFGBlock *CurBlock = Stack.back();
+ Stack.pop_back();
- const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
- if (CE && CE->getCalleeDecl() &&
- CE->getCalleeDecl()->getCanonicalDecl() == FD) {
-
- // Skip function calls which are qualified with a templated class.
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
- CE->getCallee()->IgnoreParenImpCasts())) {
- if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
- if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
- isa<TemplateSpecializationType>(NNS->getAsType())) {
- continue;
- }
- }
- }
+ unsigned ID = CurBlock->getBlockID();
+ RecursiveState CurState = States[ID];
- if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) {
- if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
- !MCE->getMethodDecl()->isVirtual()) {
- State = FoundPath;
- break;
- }
- } else {
- State = FoundPath;
- break;
+ if (CurState == FoundPathWithNoRecursiveCall) {
+ // Found a path to the exit node without a recursive call.
+ if (ExitID == ID)
+ return false;
+
+ // Only change state if the block has a recursive call.
+ if (hasRecursiveCallInPath(FD, *CurBlock))
+ CurState = FoundPath;
+ }
+
+ // Loop over successor blocks and add them to the Stack if their state
+ // changes.
+ for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I)
+ if (*I) {
+ unsigned next_ID = (*I)->getBlockID();
+ if (States[next_ID] < CurState) {
+ States[next_ID] = CurState;
+ Stack.push_back(*I);
}
}
- }
}
- for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end();
- I != E; ++I)
- if (*I)
- checkForFunctionCall(S, FD, **I, ExitID, States, State);
+ // Return true if the exit node is reachable, and only reachable through
+ // a recursive call.
+ return States[ExitID] == FoundPath;
}
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
- const Stmt *Body,
- AnalysisDeclContext &AC) {
+ const Stmt *Body, AnalysisDeclContext &AC) {
FD = FD->getCanonicalDecl();
// Only run on non-templated functions and non-templated members of
@@ -248,15 +268,8 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
if (cfg->getExit().pred_empty())
return;
- // Mark all nodes as FoundNoPath, then begin processing the entry block.
- llvm::SmallVector<RecursiveState, 16> states(cfg->getNumBlockIDs(),
- FoundNoPath);
- checkForFunctionCall(S, FD, cfg->getEntry(), cfg->getExit().getBlockID(),
- states, FoundPathWithNoRecursiveCall);
-
- // Check that the exit block is reachable. This prevents triggering the
- // warning on functions that do not terminate.
- if (states[cfg->getExit().getBlockID()] == FoundPath)
+ // Emit diagnostic if a recursive function call is detected for all paths.
+ if (checkForRecursiveFunctionCall(FD, cfg))
S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
}
@@ -492,7 +505,7 @@ struct CheckFallThroughDiagnostics {
}
};
-}
+} // anonymous namespace
/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
/// function that should return a value. Check that we don't fall off the end
@@ -600,7 +613,7 @@ public:
bool doesContainReference() const { return FoundReference; }
};
-}
+} // anonymous namespace
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
QualType VariableTy = VD->getType().getCanonicalType();
@@ -643,8 +656,7 @@ static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then,
CharSourceRange::getCharRange(If->getLocStart(),
Then->getLocStart()));
if (Else) {
- SourceLocation ElseKwLoc = Lexer::getLocForEndOfToken(
- Then->getLocEnd(), 0, S.getSourceManager(), S.getLangOpts());
+ SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getLocEnd());
Fixit2 = FixItHint::CreateRemoval(
SourceRange(ElseKwLoc, Else->getLocEnd()));
}
@@ -836,7 +848,6 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
const UninitUse &Use,
bool alwaysReportSelfInit = false) {
-
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) {
// Inspect the initializer of the variable declaration which is
// being referenced prior to its initialization. We emit
@@ -1058,7 +1069,7 @@ namespace {
Sema &S;
llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
};
-}
+} // anonymous namespace
static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
bool PerFunction) {
@@ -1090,8 +1101,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
FM.fillReachableBlocks(Cfg);
- for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) {
- const CFGBlock *B = *I;
+ for (const CFGBlock *B : llvm::reverse(*Cfg)) {
const Stmt *Label = B->getLabel();
if (!Label || !isa<SwitchCase>(Label))
@@ -1170,7 +1180,6 @@ static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
return false;
}
-
static void diagnoseRepeatedUseOfWeak(Sema &S,
const sema::FunctionScopeInfo *CurFn,
const Decl *D,
@@ -1330,20 +1339,16 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
// the same as insertion order. This is needed to obtain a deterministic
// order of diagnostics when calling flushDiagnostics().
typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
- UsesMap *uses;
+ UsesMap uses;
public:
- UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {}
+ UninitValsDiagReporter(Sema &S) : S(S) {}
~UninitValsDiagReporter() override { flushDiagnostics(); }
MappedType &getUses(const VarDecl *vd) {
- if (!uses)
- uses = new UsesMap();
-
- MappedType &V = (*uses)[vd];
+ MappedType &V = uses[vd];
if (!V.getPointer())
V.setPointer(new UsesVec());
-
return V;
}
@@ -1357,10 +1362,7 @@ public:
}
void flushDiagnostics() {
- if (!uses)
- return;
-
- for (const auto &P : *uses) {
+ for (const auto &P : uses) {
const VarDecl *vd = P.first;
const MappedType &V = P.second;
@@ -1401,7 +1403,8 @@ public:
// Release the uses vector.
delete vec;
}
- delete uses;
+
+ uses.clear();
}
private:
@@ -1413,7 +1416,7 @@ private:
});
}
};
-}
+} // anonymous namespace
namespace clang {
namespace {
@@ -1431,7 +1434,8 @@ struct SortDiagBySourceLocation {
return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
}
};
-}}
+} // anonymous namespace
+} // namespace clang
//===----------------------------------------------------------------------===//
// -Wthread-safety
@@ -1670,7 +1674,6 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
Warnings.emplace_back(std::move(Warning), getNotes());
}
-
void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
@@ -1696,10 +1699,10 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
}
void leaveFunction(const FunctionDecl* FD) override {
- CurrentFunction = 0;
+ CurrentFunction = nullptr;
}
};
-} // namespace
+} // anonymous namespace
} // namespace threadSafety
} // namespace clang
@@ -1792,7 +1795,9 @@ public:
Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
};
-}}}
+} // anonymous namespace
+} // namespace consumed
+} // namespace clang
//===----------------------------------------------------------------------===//
// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
@@ -1958,7 +1963,6 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
flushDiagnostics(S, fscope);
}
-
// Warning: check missing 'return'
if (P.enableCheckFallThrough) {
const CheckFallThroughDiagnostics &CD =
@@ -2038,7 +2042,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
}
- if (S.getLangOpts().ObjCARCWeak &&
+ if (S.getLangOpts().ObjCWeak &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart()))
diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp
index 34af6cf63c87..3c61c95ad8ec 100644
--- a/lib/Sema/AttributeList.cpp
+++ b/lib/Sema/AttributeList.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@@ -108,6 +109,19 @@ void AttributePool::takePool(AttributeList *pool) {
#include "clang/Sema/AttrParsedAttrKinds.inc"
+static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
+ AttributeList::Syntax SyntaxUsed) {
+ // Normalize the attribute name, __foo__ becomes foo. This is only allowable
+ // for GNU attributes.
+ bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
+ (SyntaxUsed == AttributeList::AS_CXX11 && ScopeName == "gnu");
+ if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
+ AttrName.endswith("__"))
+ AttrName = AttrName.slice(2, AttrName.size() - 2);
+
+ return AttrName;
+}
+
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
const IdentifierInfo *ScopeName,
Syntax SyntaxUsed) {
@@ -117,13 +131,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
if (ScopeName)
FullName += ScopeName->getName();
- // Normalize the attribute name, __foo__ becomes foo. This is only allowable
- // for GNU attributes.
- bool IsGNU = SyntaxUsed == AS_GNU || (SyntaxUsed == AS_CXX11 &&
- FullName == "gnu");
- if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
- AttrName.endswith("__"))
- AttrName = AttrName.slice(2, AttrName.size() - 2);
+ AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
// Ensure that in the case of C++11 attributes, we look for '::foo' if it is
// unscoped.
@@ -137,8 +145,9 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
unsigned AttributeList::getAttributeSpellingListIndex() const {
// Both variables will be used in tablegen generated
// attribute spell list index matching code.
- StringRef Name = AttrName->getName();
StringRef Scope = ScopeName ? ScopeName->getName() : "";
+ StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
+ (AttributeList::Syntax)SyntaxUsed);
#include "clang/Sema/AttrSpellingListIndex.inc"
@@ -155,7 +164,7 @@ struct ParsedAttrInfo {
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
const Decl *);
bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
- bool (*ExistsInTarget)(const llvm::Triple &T);
+ bool (*ExistsInTarget)(const TargetInfo &Target);
unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
};
@@ -195,8 +204,8 @@ bool AttributeList::isTypeAttr() const {
return getInfo(*this).IsType;
}
-bool AttributeList::existsInTarget(const llvm::Triple &T) const {
- return getInfo(*this).ExistsInTarget(T);
+bool AttributeList::existsInTarget(const TargetInfo &Target) const {
+ return getInfo(*this).ExistsInTarget(Target);
}
bool AttributeList::isKnownToGCC() const {
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 4a772d8972a9..8aa005102fe4 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangSema
SemaChecking.cpp
SemaCodeComplete.cpp
SemaConsumer.cpp
+ SemaCoroutine.cpp
SemaCUDA.cpp
SemaDecl.cpp
SemaDeclAttr.cpp
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 4adbb2b6af2a..d664d8704003 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -1,4 +1,4 @@
-//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
+//===--- DeclSpec.cpp - Declaration Specifier Semantic Analysis -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,29 +15,19 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
#include "clang/Sema/LocInfoType.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/ErrorHandling.h"
#include <cstring>
using namespace clang;
-static DiagnosticBuilder Diag(DiagnosticsEngine &D, SourceLocation Loc,
- unsigned DiagID) {
- return D.Report(Loc, DiagID);
-}
-
-
void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
assert(TemplateId && "NULL template-id annotation?");
Kind = IK_TemplateId;
@@ -177,7 +167,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
SourceLocation MutableLoc,
ExceptionSpecificationType
ESpecType,
- SourceLocation ESpecLoc,
+ SourceRange ESpecRange,
ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
@@ -212,7 +202,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding();
I.Fun.MutableLoc = MutableLoc.getRawEncoding();
I.Fun.ExceptionSpecType = ESpecType;
- I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding();
+ I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding();
+ I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding();
I.Fun.NumExceptions = 0;
I.Fun.Exceptions = nullptr;
I.Fun.NoexceptExpr = nullptr;
@@ -287,6 +278,7 @@ bool Declarator::isDeclarationOfFunction() const {
switch (DS.getTypeSpecType()) {
case TST_atomic:
case TST_auto:
+ case TST_auto_type:
case TST_bool:
case TST_char:
case TST_char16:
@@ -350,6 +342,11 @@ bool Declarator::isStaticMember() {
getName().OperatorFunctionId.Operator));
}
+bool Declarator::isCtorOrDtor() {
+ return (getName().getKind() == UnqualifiedId::IK_ConstructorName) ||
+ (getName().getKind() == UnqualifiedId::IK_DestructorName);
+}
+
bool DeclSpec::hasTagDefinition() const {
if (!TypeSpecOwned)
return false;
@@ -470,6 +467,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_typeofType:
case DeclSpec::TST_typeofExpr: return "typeof";
case DeclSpec::TST_auto: return "auto";
+ case DeclSpec::TST_auto_type: return "__auto_type";
case DeclSpec::TST_decltype: return "(decltype)";
case DeclSpec::TST_decltype_auto: return "decltype(auto)";
case DeclSpec::TST_underlyingType: return "__underlying_type";
@@ -508,12 +506,12 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
case SCS_extern:
case SCS_private_extern:
case SCS_static:
- if (S.getLangOpts().OpenCLVersion < 120) {
- DiagID = diag::err_opencl_unknown_type_specifier;
- PrevSpec = getSpecifierName(SC);
- return true;
- }
- break;
+ if (S.getLangOpts().OpenCLVersion < 120) {
+ DiagID = diag::err_opencl_unknown_type_specifier;
+ PrevSpec = getSpecifierName(SC);
+ return true;
+ }
+ break;
case SCS_auto:
case SCS_register:
DiagID = diag::err_opencl_unknown_type_specifier;
@@ -925,7 +923,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
-void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPolicy &Policy) {
+void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
// Before possibly changing their values, save specs as written.
SaveWrittenBuiltinSpecs();
@@ -946,10 +944,10 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
FixItHint Hints[NumLocs];
SourceLocation FirstLoc;
for (unsigned I = 0; I != NumLocs; ++I) {
- if (!ExtraLocs[I].isInvalid()) {
+ if (ExtraLocs[I].isValid()) {
if (FirstLoc.isInvalid() ||
- PP.getSourceManager().isBeforeInTranslationUnit(ExtraLocs[I],
- FirstLoc))
+ S.getSourceManager().isBeforeInTranslationUnit(ExtraLocs[I],
+ FirstLoc))
FirstLoc = ExtraLocs[I];
Hints[I] = FixItHint::CreateRemoval(ExtraLocs[I]);
}
@@ -959,7 +957,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
TypeSpecSign = TSS_unspecified;
TypeAltiVecVector = TypeAltiVecPixel = TypeAltiVecBool = false;
TypeQualifiers = 0;
- Diag(D, TSTLoc, diag::err_decltype_auto_cannot_be_combined)
+ S.Diag(TSTLoc, diag::err_decltype_auto_cannot_be_combined)
<< Hints[0] << Hints[1] << Hints[2] << Hints[3]
<< Hints[4] << Hints[5] << Hints[6] << Hints[7];
}
@@ -969,14 +967,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
if (TypeAltiVecBool) {
// Sign specifiers are not allowed with vector bool. (PIM 2.1)
if (TypeSpecSign != TSS_unspecified) {
- Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec)
+ S.Diag(TSSLoc, diag::err_invalid_vector_bool_decl_spec)
<< getSpecifierName((TSS)TypeSpecSign);
}
// Only char/int are valid with vector bool. (PIM 2.1)
if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
(TypeSpecType != TST_int)) || TypeAltiVecPixel) {
- Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
+ S.Diag(TSTLoc, diag::err_invalid_vector_bool_decl_spec)
<< (TypeAltiVecPixel ? "__pixel" :
getSpecifierName((TST)TypeSpecType, Policy));
}
@@ -984,15 +982,15 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
// Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
(TypeSpecWidth != TSW_longlong))
- Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec)
+ S.Diag(TSWLoc, diag::err_invalid_vector_bool_decl_spec)
<< getSpecifierName((TSW)TypeSpecWidth);
// vector bool long long requires VSX support or ZVector.
if ((TypeSpecWidth == TSW_longlong) &&
- (!PP.getTargetInfo().hasFeature("vsx")) &&
- (!PP.getTargetInfo().hasFeature("power8-vector")) &&
- !PP.getLangOpts().ZVector)
- Diag(D, TSTLoc, diag::err_invalid_vector_long_long_decl_spec);
+ (!S.Context.getTargetInfo().hasFeature("vsx")) &&
+ (!S.Context.getTargetInfo().hasFeature("power8-vector")) &&
+ !S.getLangOpts().ZVector)
+ S.Diag(TSTLoc, diag::err_invalid_vector_long_long_decl_spec);
// Elements of vector bool are interpreted as unsigned. (PIM 2.1)
if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
@@ -1002,20 +1000,20 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
// vector long double and vector long long double are never allowed.
// vector double is OK for Power7 and later, and ZVector.
if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong)
- Diag(D, TSWLoc, diag::err_invalid_vector_long_double_decl_spec);
- else if (!PP.getTargetInfo().hasFeature("vsx") &&
- !PP.getLangOpts().ZVector)
- Diag(D, TSTLoc, diag::err_invalid_vector_double_decl_spec);
+ S.Diag(TSWLoc, diag::err_invalid_vector_long_double_decl_spec);
+ else if (!S.Context.getTargetInfo().hasFeature("vsx") &&
+ !S.getLangOpts().ZVector)
+ S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec);
} else if (TypeSpecType == TST_float) {
// vector float is unsupported for ZVector.
- if (PP.getLangOpts().ZVector)
- Diag(D, TSTLoc, diag::err_invalid_vector_float_decl_spec);
+ if (S.getLangOpts().ZVector)
+ S.Diag(TSTLoc, diag::err_invalid_vector_float_decl_spec);
} else if (TypeSpecWidth == TSW_long) {
// vector long is unsupported for ZVector and deprecated for AltiVec.
- if (PP.getLangOpts().ZVector)
- Diag(D, TSWLoc, diag::err_invalid_vector_long_decl_spec);
+ if (S.getLangOpts().ZVector)
+ S.Diag(TSWLoc, diag::err_invalid_vector_long_decl_spec);
else
- Diag(D, TSWLoc, diag::warn_vector_long_decl_spec_combination)
+ S.Diag(TSWLoc, diag::warn_vector_long_decl_spec_combination)
<< getSpecifierName((TST)TypeSpecType, Policy);
}
@@ -1034,7 +1032,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
- Diag(D, TSSLoc, diag::err_invalid_sign_spec)
+ S.Diag(TSSLoc, diag::err_invalid_sign_spec)
<< getSpecifierName((TST)TypeSpecType, Policy);
// signed double -> double.
TypeSpecSign = TSS_unspecified;
@@ -1049,9 +1047,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
else if (TypeSpecType != TST_int) {
- Diag(D, TSWLoc,
- TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
- : diag::err_invalid_longlong_spec)
+ S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
<< getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
@@ -1061,7 +1057,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
- Diag(D, TSWLoc, diag::err_invalid_long_spec)
+ S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
<< getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
@@ -1073,17 +1069,17 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
// disallow their use. Need information about the backend.
if (TypeSpecComplex != TSC_unspecified) {
if (TypeSpecType == TST_unspecified) {
- Diag(D, TSCLoc, diag::ext_plain_complex)
+ S.Diag(TSCLoc, diag::ext_plain_complex)
<< FixItHint::CreateInsertion(
- PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
+ S.getLocForEndOfToken(getTypeSpecComplexLoc()),
" double");
TypeSpecType = TST_double; // _Complex -> _Complex double.
} else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
// Note that this intentionally doesn't include _Complex _Bool.
- if (!PP.getLangOpts().CPlusPlus)
- Diag(D, TSTLoc, diag::ext_integer_complex);
+ if (!S.getLangOpts().CPlusPlus)
+ S.Diag(TSTLoc, diag::ext_integer_complex);
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
- Diag(D, TSCLoc, diag::err_invalid_complex_spec)
+ S.Diag(TSCLoc, diag::err_invalid_complex_spec)
<< getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecComplex = TSC_unspecified;
}
@@ -1100,14 +1096,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
case SCS_static:
break;
default:
- if (PP.getSourceManager().isBeforeInTranslationUnit(
+ if (S.getSourceManager().isBeforeInTranslationUnit(
getThreadStorageClassSpecLoc(), getStorageClassSpecLoc()))
- Diag(D, getStorageClassSpecLoc(),
+ S.Diag(getStorageClassSpecLoc(),
diag::err_invalid_decl_spec_combination)
<< DeclSpec::getSpecifierName(getThreadStorageClassSpec())
<< SourceRange(getThreadStorageClassSpecLoc());
else
- Diag(D, getThreadStorageClassSpecLoc(),
+ S.Diag(getThreadStorageClassSpecLoc(),
diag::err_invalid_decl_spec_combination)
<< DeclSpec::getSpecifierName(getStorageClassSpec())
<< SourceRange(getStorageClassSpecLoc());
@@ -1121,7 +1117,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
// the type specifier is not optional, but we got 'auto' as a storage
// class specifier, then assume this is an attempt to use C++0x's 'auto'
// type specifier.
- if (PP.getLangOpts().CPlusPlus &&
+ if (S.getLangOpts().CPlusPlus &&
TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
TypeSpecType = TST_auto;
StorageClassSpec = SCS_unspecified;
@@ -1130,17 +1126,17 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
}
// Diagnose if we've recovered from an ill-formed 'auto' storage class
// specifier in a pre-C++11 dialect of C++.
- if (!PP.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto)
- Diag(D, TSTLoc, diag::ext_auto_type_specifier);
- if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus11 &&
+ if (!S.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto)
+ S.Diag(TSTLoc, diag::ext_auto_type_specifier);
+ if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11 &&
StorageClassSpec == SCS_auto)
- Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
+ S.Diag(StorageClassSpecLoc, diag::warn_auto_storage_class)
<< FixItHint::CreateRemoval(StorageClassSpecLoc);
if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
- Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type)
+ S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type)
<< (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
if (Constexpr_specified)
- Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr);
+ S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr);
// C++ [class.friend]p6:
// No storage-class-specifier shall appear in the decl-specifier-seq
@@ -1164,7 +1160,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
ThreadHint = FixItHint::CreateRemoval(SCLoc);
}
- Diag(D, SCLoc, diag::err_friend_decl_spec)
+ S.Diag(SCLoc, diag::err_friend_decl_spec)
<< SpecName << StorageHint << ThreadHint;
ClearStorageClassSpecs();
@@ -1190,7 +1186,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
}
FixItHint Hint = FixItHint::CreateRemoval(SCLoc);
- Diag(D, SCLoc, diag::err_friend_decl_spec)
+ S.Diag(SCLoc, diag::err_friend_decl_spec)
<< Keyword << Hint;
FS_virtual_specified = FS_explicit_specified = false;
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 775fe85740d4..c394d24d5fdc 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -147,9 +147,12 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
if (VD->hasLocalStorage()) {
switch (VD->getType().isDestructedType()) {
case QualType::DK_objc_strong_lifetime:
+ return ScopePair(diag::note_protected_by_objc_strong_init,
+ diag::note_exits_objc_strong);
+
case QualType::DK_objc_weak_lifetime:
- return ScopePair(diag::note_protected_by_objc_ownership,
- diag::note_exits_objc_ownership);
+ return ScopePair(diag::note_protected_by_objc_weak_init,
+ diag::note_exits_objc_weak);
case QualType::DK_cxx_destructor:
OutDiag = diag::note_exits_dtor;
diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index 9ecb5a7fefbc..0f93421ac21b 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -107,15 +107,11 @@ void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC)
Sources[i]->completeVisibleDeclsMap(DC);
}
-ExternalLoadResult MultiplexExternalSemaSource::
-FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result) {
+void MultiplexExternalSemaSource::FindExternalLexicalDecls(
+ const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result) {
for(size_t i = 0; i < Sources.size(); ++i)
- // FIXME: The semantics of the return result is unclear to me...
- Sources[i]->FindExternalLexicalDecls(DC, isKindWeWant, Result);
-
- return ELR_Success;
+ Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result);
}
void MultiplexExternalSemaSource::FindFileRegionDecls(FileID File,
diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp
index f80eadf18d56..cbd7ef7abb41 100644
--- a/lib/Sema/ScopeInfo.cpp
+++ b/lib/Sema/ScopeInfo.cpp
@@ -33,11 +33,14 @@ void FunctionScopeInfo::Clear() {
ObjCWarnForNoDesignatedInitChain = false;
ObjCIsSecondaryInit = false;
ObjCWarnForNoInitDelegation = false;
+ FirstReturnLoc = SourceLocation();
FirstCXXTryLoc = SourceLocation();
FirstSEHTryLoc = SourceLocation();
SwitchStack.clear();
Returns.clear();
+ CoroutinePromise = nullptr;
+ CoroutineStmts.clear();
ErrorTrap.reset();
PossiblyUnreachableDiags.clear();
WeakObjectUses.clear();
@@ -234,5 +237,4 @@ void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD,
FunctionScopeInfo::~FunctionScopeInfo() { }
BlockScopeInfo::~BlockScopeInfo() { }
-LambdaScopeInfo::~LambdaScopeInfo() { }
CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 18d7e9dcf548..39b8cc9f0c63 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -40,7 +40,6 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
-#include "llvm/Support/CrashRecoveryContext.h"
using namespace clang;
using namespace sema;
@@ -121,8 +120,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
FieldCollector.reset(new CXXFieldCollector());
// Tell diagnostics how to render things from the AST library.
- PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
- &Context);
+ Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context);
ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false);
@@ -139,10 +137,6 @@ void Sema::addImplicitTypedef(StringRef Name, QualType T) {
}
void Sema::Initialize() {
- // Tell the AST consumer about this Sema object.
- Consumer.Initialize(Context);
-
- // FIXME: Isn't this redundant with the initialization above?
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
SC->InitializeSema(*this);
@@ -155,6 +149,9 @@ void Sema::Initialize() {
// will not be able to merge any duplicate __va_list_tag decls correctly.
VAListTagName = PP.getIdentifierInfo("__va_list_tag");
+ if (!TUScope)
+ return;
+
// Initialize predefined 128-bit integer types, if needed.
if (Context.getTargetInfo().hasInt128Type()) {
// If either of the 128-bit integer types are unavailable to name lookup,
@@ -170,7 +167,7 @@ void Sema::Initialize() {
// Initialize predefined Objective-C types:
- if (PP.getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC1) {
// If 'SEL' does not yet refer to any declarations, make it refer to the
// predefined 'SEL'.
DeclarationName SEL = &Context.Idents.get("SEL");
@@ -195,8 +192,8 @@ void Sema::Initialize() {
}
// Initialize Microsoft "predefined C++ types".
- if (PP.getLangOpts().MSVCCompat) {
- if (PP.getLangOpts().CPlusPlus &&
+ if (getLangOpts().MSVCCompat) {
+ if (getLangOpts().CPlusPlus &&
IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class),
TUScope);
@@ -205,7 +202,7 @@ void Sema::Initialize() {
}
// Initialize predefined OpenCL types.
- if (PP.getLangOpts().OpenCL) {
+ if (getLangOpts().OpenCL) {
addImplicitTypedef("image1d_t", Context.OCLImage1dTy);
addImplicitTypedef("image1d_array_t", Context.OCLImage1dArrayTy);
addImplicitTypedef("image1d_buffer_t", Context.OCLImage1dBufferTy);
@@ -215,6 +212,18 @@ void Sema::Initialize() {
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
if (getLangOpts().OpenCLVersion >= 200) {
+ addImplicitTypedef("image2d_depth_t", Context.OCLImage2dDepthTy);
+ addImplicitTypedef("image2d_array_depth_t",
+ Context.OCLImage2dArrayDepthTy);
+ addImplicitTypedef("image2d_msaa_t", Context.OCLImage2dMSAATy);
+ addImplicitTypedef("image2d_array_msaa_t", Context.OCLImage2dArrayMSAATy);
+ addImplicitTypedef("image2d_msaa_depth_t", Context.OCLImage2dMSAADepthTy);
+ addImplicitTypedef("image2d_array_msaa_depth_t",
+ Context.OCLImage2dArrayMSAADepthTy);
+ addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
+ addImplicitTypedef("queue_t", Context.OCLQueueTy);
+ addImplicitTypedef("ndrange_t", Context.OCLNDRangeTy);
+ addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
addImplicitTypedef("atomic_uint",
Context.getAtomicType(Context.UnsignedIntTy));
@@ -239,6 +248,12 @@ void Sema::Initialize() {
}
}
+ if (Context.getTargetInfo().hasBuiltinMSVaList()) {
+ DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
+ if (IdResolver.begin(MSVaList) == IdResolver.end())
+ PushOnScopeChains(Context.getBuiltinMSVaListDecl(), TUScope);
+ }
+
DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
@@ -280,7 +295,7 @@ Sema::~Sema() {
/// make the relevant declaration unavailable instead of erroring, do
/// so and return true.
bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
- StringRef msg) {
+ UnavailableAttr::ImplicitReason reason) {
// If we're not in a function, it's an error.
FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext);
if (!fn) return false;
@@ -296,7 +311,7 @@ bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
// If the function is already unavailable, it's not an error.
if (fn->hasAttr<UnavailableAttr>()) return true;
- fn->addAttr(UnavailableAttr::CreateImplicit(Context, msg, loc));
+ fn->addAttr(UnavailableAttr::CreateImplicit(Context, "", reason, loc));
return true;
}
@@ -334,6 +349,20 @@ void Sema::PrintStats() const {
AnalysisWarnings.PrintStats();
}
+void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
+ QualType SrcType,
+ SourceLocation Loc) {
+ Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context);
+ if (!ExprNullability || *ExprNullability != NullabilityKind::Nullable)
+ return;
+
+ Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context);
+ if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull)
+ return;
+
+ Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType;
+}
+
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// The result is of the given category.
@@ -357,18 +386,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue");
#endif
- // Check whether we're implicitly casting from a nullable type to a nonnull
- // type.
- if (auto exprNullability = E->getType()->getNullability(Context)) {
- if (*exprNullability == NullabilityKind::Nullable) {
- if (auto typeNullability = Ty->getNullability(Context)) {
- if (*typeNullability == NullabilityKind::NonNull) {
- Diag(E->getLocStart(), diag::warn_nullability_lost)
- << E->getType() << Ty;
- }
- }
- }
- }
+ diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart());
QualType ExprTy = Context.getCanonicalType(E->getType());
QualType TypeTy = Context.getCanonicalType(Ty);
@@ -689,6 +707,9 @@ void Sema::ActOnEndOfTranslationUnit() {
assert(DelayedDefaultedMemberExceptionSpecs.empty());
assert(DelayedExceptionSpecChecks.empty());
+ // All dllexport classes should have been processed already.
+ assert(DelayedDllExportClasses.empty());
+
// Remove file scoped decls that turned out to be used.
UnusedFileScopedDecls.erase(
std::remove_if(UnusedFileScopedDecls.begin(nullptr, true),
@@ -708,8 +729,15 @@ void Sema::ActOnEndOfTranslationUnit() {
if (WeakID.second.getUsed())
continue;
- Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared)
- << WeakID.first;
+ Decl *PrevDecl = LookupSingleName(TUScope, WeakID.first, SourceLocation(),
+ LookupOrdinaryName);
+ if (PrevDecl != nullptr &&
+ !(isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)))
+ Diag(WeakID.second.getLocation(), diag::warn_attribute_wrong_decl_type)
+ << "'weak'" << ExpectedVariableOrFunction;
+ else
+ Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared)
+ << WeakID.first;
}
if (LangOpts.CPlusPlus11 &&
@@ -1443,7 +1471,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
// arguments and that it returns something of a reasonable type,
// so we can emit a fixit and carry on pretending that E was
// actually a CallExpr.
- SourceLocation ParenInsertionLoc = PP.getLocForEndOfToken(Range.getEnd());
+ SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
Diag(Loc, PD)
<< /*zero-arg*/ 1 << Range
<< (IsCallableWithAppend(E.get())
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 0e973cc5ebaa..e9772bc52049 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -182,15 +182,20 @@ struct AccessTarget : public AccessedEntity {
class SavedInstanceContext {
public:
+ SavedInstanceContext(SavedInstanceContext &&S)
+ : Target(S.Target), Has(S.Has) {
+ S.Target = nullptr;
+ }
~SavedInstanceContext() {
- Target.HasInstanceContext = Has;
+ if (Target)
+ Target->HasInstanceContext = Has;
}
private:
friend struct AccessTarget;
explicit SavedInstanceContext(AccessTarget &Target)
- : Target(Target), Has(Target.HasInstanceContext) {}
- AccessTarget &Target;
+ : Target(&Target), Has(Target.HasInstanceContext) {}
+ AccessTarget *Target;
bool Has;
};
@@ -1766,7 +1771,7 @@ Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
case AR_inaccessible: return Sema::AR_inaccessible;
case AR_dependent: return Sema::AR_dependent;
}
- llvm_unreachable("falling off end");
+ llvm_unreachable("invalid access result");
}
Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp
index 5973500826e3..61dfdd3f7206 100644
--- a/lib/Sema/SemaCUDA.cpp
+++ b/lib/Sema/SemaCUDA.cpp
@@ -60,8 +60,101 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
return CFT_Host;
}
+// * CUDA Call preference table
+//
+// F - from,
+// T - to
+// Ph - preference in host mode
+// Pd - preference in device mode
+// H - handled in (x)
+// Preferences: b-best, f-fallback, l-last resort, n-never.
+//
+// | F | T | Ph | Pd | H |
+// |----+----+----+----+-----+
+// | d | d | b | b | (b) |
+// | d | g | n | n | (a) |
+// | d | h | l | l | (e) |
+// | d | hd | f | f | (c) |
+// | g | d | b | b | (b) |
+// | g | g | n | n | (a) |
+// | g | h | l | l | (e) |
+// | g | hd | f | f | (c) |
+// | h | d | l | l | (e) |
+// | h | g | b | b | (b) |
+// | h | h | b | b | (b) |
+// | h | hd | f | f | (c) |
+// | hd | d | l | f | (d) |
+// | hd | g | f | n |(d/a)|
+// | hd | h | f | l | (d) |
+// | hd | hd | b | b | (b) |
+
+Sema::CUDAFunctionPreference
+Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
+ const FunctionDecl *Callee) {
+ assert(getLangOpts().CUDATargetOverloads &&
+ "Should not be called w/o enabled target overloads.");
+
+ assert(Callee && "Callee must be valid.");
+ CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee);
+ CUDAFunctionTarget CallerTarget =
+ (Caller != nullptr) ? IdentifyCUDATarget(Caller) : Sema::CFT_Host;
+
+ // If one of the targets is invalid, the check always fails, no matter what
+ // the other target is.
+ if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget)
+ return CFP_Never;
+
+ // (a) Can't call global from some contexts until we support CUDA's
+ // dynamic parallelism.
+ if (CalleeTarget == CFT_Global &&
+ (CallerTarget == CFT_Global || CallerTarget == CFT_Device ||
+ (CallerTarget == CFT_HostDevice && getLangOpts().CUDAIsDevice)))
+ return CFP_Never;
+
+ // (b) Best case scenarios
+ if (CalleeTarget == CallerTarget ||
+ (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) ||
+ (CallerTarget == CFT_Global && CalleeTarget == CFT_Device))
+ return CFP_Best;
+
+ // (c) Calling HostDevice is OK as a fallback that works for everyone.
+ if (CalleeTarget == CFT_HostDevice)
+ return CFP_Fallback;
+
+ // Figure out what should be returned 'last resort' cases. Normally
+ // those would not be allowed, but we'll consider them if
+ // CUDADisableTargetCallChecks is true.
+ CUDAFunctionPreference QuestionableResult =
+ getLangOpts().CUDADisableTargetCallChecks ? CFP_LastResort : CFP_Never;
+
+ // (d) HostDevice behavior depends on compilation mode.
+ if (CallerTarget == CFT_HostDevice) {
+ // Calling a function that matches compilation mode is OK.
+ // Calling a function from the other side is frowned upon.
+ if (getLangOpts().CUDAIsDevice)
+ return CalleeTarget == CFT_Device ? CFP_Fallback : QuestionableResult;
+ else
+ return (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global)
+ ? CFP_Fallback
+ : QuestionableResult;
+ }
+
+ // (e) Calling across device/host boundary is not something you should do.
+ if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) ||
+ (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) ||
+ (CallerTarget == CFT_Global && CalleeTarget == CFT_Host))
+ return QuestionableResult;
+
+ llvm_unreachable("All cases should've been handled by now.");
+}
+
bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
const FunctionDecl *Callee) {
+ // With target overloads enabled, we only disallow calling
+ // combinations with CFP_Never.
+ if (getLangOpts().CUDATargetOverloads)
+ return IdentifyCUDAPreference(Caller,Callee) == CFP_Never;
+
// The CUDADisableTargetCallChecks short-circuits this check: we assume all
// cross-target calls are valid.
if (getLangOpts().CUDADisableTargetCallChecks)
@@ -117,6 +210,57 @@ bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
return false;
}
+template <typename T, typename FetchDeclFn>
+static void EraseUnwantedCUDAMatchesImpl(Sema &S, const FunctionDecl *Caller,
+ llvm::SmallVectorImpl<T> &Matches,
+ FetchDeclFn FetchDecl) {
+ assert(S.getLangOpts().CUDATargetOverloads &&
+ "Should not be called w/o enabled target overloads.");
+ if (Matches.size() <= 1)
+ return;
+
+ // Find the best call preference among the functions in Matches.
+ Sema::CUDAFunctionPreference P, BestCFP = Sema::CFP_Never;
+ for (auto const &Match : Matches) {
+ P = S.IdentifyCUDAPreference(Caller, FetchDecl(Match));
+ if (P > BestCFP)
+ BestCFP = P;
+ }
+
+ // Erase all functions with lower priority.
+ for (unsigned I = 0, N = Matches.size(); I != N;)
+ if (S.IdentifyCUDAPreference(Caller, FetchDecl(Matches[I])) < BestCFP) {
+ Matches[I] = Matches[--N];
+ Matches.resize(N);
+ } else {
+ ++I;
+ }
+}
+
+void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
+ SmallVectorImpl<FunctionDecl *> &Matches){
+ EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
+ *this, Caller, Matches, [](const FunctionDecl *item) { return item; });
+}
+
+void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
+ SmallVectorImpl<DeclAccessPair> &Matches) {
+ EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
+ *this, Caller, Matches, [](const DeclAccessPair &item) {
+ return dyn_cast<FunctionDecl>(item.getDecl());
+ });
+}
+
+void Sema::EraseUnwantedCUDAMatches(
+ const FunctionDecl *Caller,
+ SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){
+ EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
+ *this, Caller, Matches,
+ [](const std::pair<DeclAccessPair, FunctionDecl *> &item) {
+ return dyn_cast<FunctionDecl>(item.second);
+ });
+}
+
/// When an implicitly-declared special member has to invoke more than one
/// base/field special member, conflicts may occur in the targets of these
/// members. For example, if one base's member __host__ and another's is
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 9e146ed3a642..f7aace625a92 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -291,8 +291,10 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
if (!SD)
return false;
+ SD = SD->getUnderlyingDecl();
+
// Namespace and namespace aliases are fine.
- if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD))
+ if (isa<NamespaceDecl>(SD))
return true;
if (!isa<TypeDecl>(SD))
@@ -396,10 +398,7 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
}
Found.suppressDiagnostics();
- if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
- return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
-
- return false;
+ return Found.getAsSingle<NamespaceDecl>();
}
namespace {
@@ -533,6 +532,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
LookupName(Found, S);
}
+ if (Found.isAmbiguous())
+ return true;
+
// If we performed lookup into a dependent context and did not find anything,
// that's fine: just build a dependent nested-name-specifier.
if (Found.empty() && isDependent &&
@@ -551,8 +553,6 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
return false;
}
- // FIXME: Deal with ambiguities cleanly.
-
if (Found.empty() && !ErrorRecoveryLookup) {
// If identifier is not found as class-name-or-namespace-name, but is found
// as other entity, don't look for typos.
@@ -562,6 +562,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
else if (S && !isDependent)
LookupName(R, S);
if (!R.empty()) {
+ // Don't diagnose problems with this speculative lookup.
+ R.suppressDiagnostics();
// The identifier is found in ordinary lookup. If correction to colon is
// allowed, suggest replacement to ':'.
if (IsCorrectedToColon) {
@@ -604,7 +606,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
<< Name);
- if (NamedDecl *ND = Corrected.getCorrectionDecl())
+ if (NamedDecl *ND = Corrected.getFoundDecl())
Found.addDecl(ND);
Found.setLookupName(Corrected.getCorrection());
} else {
@@ -612,7 +614,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
}
}
- NamedDecl *SD = Found.getAsSingle<NamedDecl>();
+ NamedDecl *SD =
+ Found.isSingleResult() ? Found.getRepresentativeDecl() : nullptr;
bool IsExtension = false;
bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, &IsExtension);
if (!AcceptSpec && IsExtension) {
@@ -684,7 +687,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
return false;
}
- QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
+ QualType T =
+ Context.getTypeDeclType(cast<TypeDecl>(SD->getUnderlyingDecl()));
TypeLocBuilder TLB;
if (isa<InjectedClassNameType>(T)) {
InjectedClassNameTypeLoc InjectedTL
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index c0754ba7902a..07b058911c2d 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -160,19 +160,19 @@ static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
unsigned &msg);
static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind,
CXXCastPath &BasePath);
static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind,
CXXCastPath &BasePath);
static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
CanQualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
QualType OrigSrcType,
QualType OrigDestType, unsigned &msg,
CastKind &Kind,
@@ -180,7 +180,7 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr,
QualType SrcType,
QualType DestType,bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind,
CXXCastPath &BasePath);
@@ -188,13 +188,13 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExp
static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType,
Sema::CheckedConversionKind CCK,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg, CastKind &Kind,
bool ListInitialization);
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType,
Sema::CheckedConversionKind CCK,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath,
bool ListInitialization);
@@ -203,7 +203,7 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
unsigned &msg);
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind);
@@ -489,9 +489,9 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
QualType *TheOffendingDestType = nullptr,
Qualifiers *CastAwayQualifiers = nullptr) {
// If the only checking we care about is for Objective-C lifetime qualifiers,
- // and we're not in ARC mode, there's nothing to check.
+ // and we're not in ObjC mode, there's nothing to check.
if (!CheckCVR && CheckObjCLifetime &&
- !Self.Context.getLangOpts().ObjCAutoRefCount)
+ !Self.Context.getLangOpts().ObjC1)
return false;
// Casting away constness is defined in C++ 5.2.11p8 with reference to
@@ -683,7 +683,8 @@ void CastOperation::CheckDynamicCast() {
// C++ 5.2.7p5
// Upcasts are resolved statically.
- if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) {
+ if (DestRecord &&
+ Self.IsDerivedFrom(OpRange.getBegin(), SrcPointee, DestPointee)) {
if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
OpRange.getBegin(), OpRange,
&BasePath)) {
@@ -943,7 +944,7 @@ void CastOperation::CheckStaticCast() {
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType,
Sema::CheckedConversionKind CCK,
- const SourceRange &OpRange, unsigned &msg,
+ SourceRange OpRange, unsigned &msg,
CastKind &Kind, CXXCastPath &BasePath,
bool ListInitialization) {
// Determine whether we have the semantics of a C-style cast.
@@ -1171,7 +1172,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
Kind = CK_DerivedToBase;
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths))
+ if (!Self.IsDerivedFrom(SrcExpr->getLocStart(), SrcExpr->getType(),
+ R->getPointeeType(), Paths))
return TC_NotApplicable;
Self.BuildBasePathArray(Paths, BasePath);
@@ -1184,7 +1186,7 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
/// Tests whether a conversion according to C++ 5.2.9p5 is valid.
TryCastResult
TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
- bool CStyle, const SourceRange &OpRange,
+ bool CStyle, SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath) {
// C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
@@ -1222,7 +1224,7 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
/// Tests whether a conversion according to C++ 5.2.9p8 is valid.
TryCastResult
TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
- bool CStyle, const SourceRange &OpRange,
+ bool CStyle, SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath) {
// C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
@@ -1256,12 +1258,12 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
/// DestType is possible and allowed.
TryCastResult
TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
- bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
+ bool CStyle, SourceRange OpRange, QualType OrigSrcType,
QualType OrigDestType, unsigned &msg,
CastKind &Kind, CXXCastPath &BasePath) {
// We can only work with complete types. But don't complain if it doesn't work
- if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0) ||
- Self.RequireCompleteType(OpRange.getBegin(), DestType, 0))
+ if (!Self.isCompleteType(OpRange.getBegin(), SrcType) ||
+ !Self.isCompleteType(OpRange.getBegin(), DestType))
return TC_NotApplicable;
// Downcast can only happen in class hierarchies, so we need classes.
@@ -1271,7 +1273,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) {
+ if (!Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths)) {
return TC_NotApplicable;
}
@@ -1307,7 +1309,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
if (!Paths.isRecordingPaths()) {
Paths.clear();
Paths.setRecordingPaths(true);
- Self.IsDerivedFrom(DestType, SrcType, Paths);
+ Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths);
}
std::string PathDisplayStr;
std::set<unsigned> DisplayedPaths;
@@ -1372,7 +1374,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
TryCastResult
TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath) {
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
@@ -1398,6 +1400,11 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
return TC_NotApplicable;
}
+ // Lock down the inheritance model right now in MS ABI, whether or not the
+ // pointee types are the same.
+ if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft())
+ (void)Self.isCompleteType(OpRange.getBegin(), SrcType);
+
// T == T, modulo cv
if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(),
DestMemPtr->getPointeeType()))
@@ -1408,16 +1415,15 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
QualType DestClass(DestMemPtr->getClass(), 0);
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (Self.RequireCompleteType(OpRange.getBegin(), SrcClass, 0) ||
- !Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
+ if (!Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths))
return TC_NotApplicable;
- }
// B is a base of D. But is it an allowed base? If not, it's a hard error.
if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) {
Paths.clear();
Paths.setRecordingPaths(true);
- bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths);
+ bool StillOkay =
+ Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths);
assert(StillOkay);
(void)StillOkay;
std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths);
@@ -1484,7 +1490,7 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
TryCastResult
TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
Sema::CheckedConversionKind CCK,
- const SourceRange &OpRange, unsigned &msg,
+ SourceRange OpRange, unsigned &msg,
CastKind &Kind, bool ListInitialization) {
if (DestType->isRecordType()) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
@@ -1494,10 +1500,6 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
msg = 0;
return TC_Failed;
}
- } else if (DestType->isMemberPointerType()) {
- if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
- }
}
InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
@@ -1750,7 +1752,7 @@ static void checkIntToPointerCast(bool CStyle, SourceLocation Loc,
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind) {
bool IsLValueCast = false;
@@ -1845,8 +1847,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
// We need to determine the inheritance model that the class will use if
// haven't yet.
- Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0);
- Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
+ (void)Self.isCompleteType(OpRange.getBegin(), SrcType);
+ (void)Self.isCompleteType(OpRange.getBegin(), DestType);
}
// Don't allow casting between member pointers of different sizes.
@@ -1877,28 +1879,29 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return TC_Success;
}
+ // Allow reinterpret_casts between vectors of the same size and
+ // between vectors and integers of the same size.
bool destIsVector = DestType->isVectorType();
bool srcIsVector = SrcType->isVectorType();
if (srcIsVector || destIsVector) {
- // FIXME: Should this also apply to floating point types?
- bool srcIsScalar = SrcType->isIntegralType(Self.Context);
- bool destIsScalar = DestType->isIntegralType(Self.Context);
-
- // Check if this is a cast between a vector and something else.
- if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) &&
- !(srcIsVector && destIsVector))
+ // The non-vector type, if any, must have integral type. This is
+ // the same rule that C vector casts use; note, however, that enum
+ // types are not integral in C++.
+ if ((!destIsVector && !DestType->isIntegralType(Self.Context)) ||
+ (!srcIsVector && !SrcType->isIntegralType(Self.Context)))
return TC_NotApplicable;
- // If both types have the same size, we can successfully cast.
- if (Self.Context.getTypeSize(SrcType)
- == Self.Context.getTypeSize(DestType)) {
+ // The size we want to consider is eltCount * eltSize.
+ // That's exactly what the lax-conversion rules will check.
+ if (Self.areLaxCompatibleVectorTypes(SrcType, DestType)) {
Kind = CK_BitCast;
return TC_Success;
}
-
- if (destIsScalar)
+
+ // Otherwise, pick a reasonable diagnostic.
+ if (!destIsVector)
msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
- else if (srcIsScalar)
+ else if (!srcIsVector)
msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size;
else
msg = diag::err_bad_cxx_cast_vector_to_vector_different_size;
@@ -2237,6 +2240,16 @@ void CastOperation::CheckCStyleCast() {
return;
}
+ // Overloads are allowed with C extensions, so we need to support them.
+ if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+ DeclAccessPair DAP;
+ if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction(
+ SrcExpr.get(), DestType, /*Complain=*/true, DAP))
+ SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD);
+ else
+ return;
+ assert(SrcExpr.isUsable());
+ }
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
if (SrcExpr.isInvalid())
return;
@@ -2480,8 +2493,11 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false);
if (Op.SrcExpr.isInvalid())
return ExprError();
-
- if (CXXConstructExpr *ConstructExpr = dyn_cast<CXXConstructExpr>(Op.SrcExpr.get()))
+
+ auto *SubExpr = Op.SrcExpr.get();
+ if (auto *BindExpr = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
+ SubExpr = BindExpr->getSubExpr();
+ if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr))
ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 1a8ab6e209e5..59d51f7e84ca 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/Analyses/FormatString.h"
@@ -111,6 +112,39 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
return false;
}
+static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
+ if (checkArgCount(S, TheCall, 3))
+ return true;
+
+ // First two arguments should be integers.
+ for (unsigned I = 0; I < 2; ++I) {
+ Expr *Arg = TheCall->getArg(I);
+ QualType Ty = Arg->getType();
+ if (!Ty->isIntegerType()) {
+ S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_int)
+ << Ty << Arg->getSourceRange();
+ return true;
+ }
+ }
+
+ // Third argument should be a pointer to a non-const integer.
+ // IRGen correctly handles volatile, restrict, and address spaces, and
+ // the other qualifiers aren't possible.
+ {
+ Expr *Arg = TheCall->getArg(2);
+ QualType Ty = Arg->getType();
+ const auto *PtrTy = Ty->getAs<PointerType>();
+ if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() &&
+ !PtrTy->getPointeeType().isConstQualified())) {
+ S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_ptr_int)
+ << Ty << Arg->getSourceRange();
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
CallExpr *TheCall, unsigned SizeIdx,
unsigned DstSizeIdx) {
@@ -440,6 +474,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__sync_swap_8:
case Builtin::BI__sync_swap_16:
return SemaBuiltinAtomicOverloaded(TheCallResult);
+ case Builtin::BI__builtin_nontemporal_load:
+ case Builtin::BI__builtin_nontemporal_store:
+ return SemaBuiltinNontemporalOverloaded(TheCallResult);
#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
case Builtin::BI##ID: \
@@ -453,6 +490,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaBuiltinAddressof(*this, TheCall))
return ExprError();
break;
+ case Builtin::BI__builtin_add_overflow:
+ case Builtin::BI__builtin_sub_overflow:
+ case Builtin::BI__builtin_mul_overflow:
+ if (SemaBuiltinOverflow(*this, TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_operator_new:
case Builtin::BI__builtin_operator_delete:
if (!getLangOpts().CPlusPlus) {
@@ -525,7 +568,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
// Since the target specific builtins for each arch overlap, only check those
// of the arch we are compiling for.
- if (BuiltinID >= Builtin::FirstTSBuiltin) {
+ if (Context.BuiltinInfo.isTSBuiltin(BuiltinID)) {
switch (Context.getTargetInfo().getTriple().getArch()) {
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -1027,12 +1070,34 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
+/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
+/// This checks that the target supports __builtin_cpu_supports and
+/// that the string argument is constant and valid.
+static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) {
+ Expr *Arg = TheCall->getArg(0);
+
+ // Check if the argument is a string literal.
+ if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
+ return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ << Arg->getSourceRange();
+
+ // Check the contents of the string.
+ StringRef Feature =
+ cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
+ if (!S.Context.getTargetInfo().validateCpuSupports(Feature))
+ return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports)
+ << Arg->getSourceRange();
+ return false;
+}
+
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
default: return false;
case X86::BI__builtin_cpu_supports:
- return SemaBuiltinCpuSupports(TheCall);
+ return SemaBuiltinCpuSupports(*this, TheCall);
+ case X86::BI__builtin_ms_va_start:
+ return SemaBuiltinMSVAStart(TheCall);
case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break;
case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break;
case X86::BI__builtin_ia32_vpermil2pd:
@@ -1115,8 +1180,7 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
/// Checks if a the given expression evaluates to null.
///
/// \brief Returns true if the value evaluates to null.
-static bool CheckNonNullExpr(Sema &S,
- const Expr *Expr) {
+static bool CheckNonNullExpr(Sema &S, const Expr *Expr) {
// If the expression has non-null type, it doesn't evaluate to null.
if (auto nullability
= Expr->IgnoreImplicit()->getType()->getNullability(S.Context)) {
@@ -1145,7 +1209,8 @@ static void CheckNonNullArgument(Sema &S,
const Expr *ArgExpr,
SourceLocation CallSiteLoc) {
if (CheckNonNullExpr(S, ArgExpr))
- S.Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
+ S.DiagRuntimeBehavior(CallSiteLoc, ArgExpr,
+ S.PDiag(diag::warn_null_arg) << ArgExpr->getSourceRange());
}
bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {
@@ -1638,6 +1703,12 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
return ExprError();
}
ValType = AtomTy->getAs<AtomicType>()->getValueType();
+ } else if (Form != Load && Op != AtomicExpr::AO__atomic_load) {
+ if (ValType.isConstQualified()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer)
+ << Ptr->getType() << Ptr->getSourceRange();
+ return ExprError();
+ }
}
// For an arithmetic operation, the implied arithmetic must be well-formed.
@@ -1675,9 +1746,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
return ExprError();
}
- // FIXME: For any builtin other than a load, the ValType must not be
- // const-qualified.
-
switch (ValType.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
@@ -1710,6 +1778,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
if (!IsC11 && !IsN)
ByValType = Ptr->getType();
+ // FIXME: __atomic_load allows the first argument to be a a pointer to const
+ // but not the second argument. We need to manually remove possible const
+ // qualifiers.
+
// The first argument --- the pointer --- has a fixed type; we
// deduce the types of the rest of the arguments accordingly. Walk
// the remaining arguments, converting them to the deduced value type.
@@ -1729,8 +1801,17 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
Ty = ByValType;
else if (Form == Arithmetic)
Ty = Context.getPointerDiffType();
- else
- Ty = Context.getPointerType(ValType.getUnqualifiedType());
+ else {
+ Expr *ValArg = TheCall->getArg(i);
+ unsigned AS = 0;
+ // Keep address space of non-atomic pointer type.
+ if (const PointerType *PtrTy =
+ ValArg->getType()->getAs<PointerType>()) {
+ AS = PtrTy->getPointeeType().getAddressSpace();
+ }
+ Ty = Context.getPointerType(
+ Context.getAddrSpaceQualType(ValType.getUnqualifiedType(), AS));
+ }
break;
case 2:
// The third argument to compare_exchange / GNU exchange is a
@@ -2142,7 +2223,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// Get the decl for the concrete builtin from this, we can tell what the
// concrete integer type we should convert to is.
unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
- const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID);
+ const char *NewBuiltinName = Context.BuiltinInfo.getName(NewBuiltinID);
FunctionDecl *NewBuiltinDecl;
if (NewBuiltinID == BuiltinID)
NewBuiltinDecl = FDecl;
@@ -2209,6 +2290,78 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
return TheCallResult;
}
+/// SemaBuiltinNontemporalOverloaded - We have a call to
+/// __builtin_nontemporal_store or __builtin_nontemporal_load, which is an
+/// overloaded function based on the pointer type of its last argument.
+///
+/// This function goes through and does final semantic checking for these
+/// builtins.
+ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) {
+ CallExpr *TheCall = (CallExpr *)TheCallResult.get();
+ DeclRefExpr *DRE =
+ cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+ FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
+ unsigned BuiltinID = FDecl->getBuiltinID();
+ assert((BuiltinID == Builtin::BI__builtin_nontemporal_store ||
+ BuiltinID == Builtin::BI__builtin_nontemporal_load) &&
+ "Unexpected nontemporal load/store builtin!");
+ bool isStore = BuiltinID == Builtin::BI__builtin_nontemporal_store;
+ unsigned numArgs = isStore ? 2 : 1;
+
+ // Ensure that we have the proper number of arguments.
+ if (checkArgCount(*this, TheCall, numArgs))
+ return ExprError();
+
+ // Inspect the last argument of the nontemporal builtin. This should always
+ // be a pointer type, from which we imply the type of the memory access.
+ // Because it is a pointer type, we don't have to worry about any implicit
+ // casts here.
+ Expr *PointerArg = TheCall->getArg(numArgs - 1);
+ ExprResult PointerArgResult =
+ DefaultFunctionArrayLvalueConversion(PointerArg);
+
+ if (PointerArgResult.isInvalid())
+ return ExprError();
+ PointerArg = PointerArgResult.get();
+ TheCall->setArg(numArgs - 1, PointerArg);
+
+ const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
+ if (!pointerType) {
+ Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_must_be_pointer)
+ << PointerArg->getType() << PointerArg->getSourceRange();
+ return ExprError();
+ }
+
+ QualType ValType = pointerType->getPointeeType();
+
+ // Strip any qualifiers off ValType.
+ ValType = ValType.getUnqualifiedType();
+ if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
+ !ValType->isBlockPointerType() && !ValType->isFloatingType() &&
+ !ValType->isVectorType()) {
+ Diag(DRE->getLocStart(),
+ diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector)
+ << PointerArg->getType() << PointerArg->getSourceRange();
+ return ExprError();
+ }
+
+ if (!isStore) {
+ TheCall->setType(ValType);
+ return TheCallResult;
+ }
+
+ ExprResult ValArg = TheCall->getArg(0);
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, ValType, /*consume*/ false);
+ ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg);
+ if (ValArg.isInvalid())
+ return ExprError();
+
+ TheCall->setArg(0, ValArg.get());
+ TheCall->setType(Context.VoidTy);
+ return TheCallResult;
+}
+
/// CheckObjCString - Checks that the argument to the builtin
/// CFString constructor is correct
/// Note: It might also make sense to do the UTF-16 conversion here (would
@@ -2241,9 +2394,10 @@ bool Sema::CheckObjCString(Expr *Arg) {
return false;
}
-/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity.
-/// Emit an error and return true on failure, return false on success.
-bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start'
+/// for validity. Emit an error and return true on failure; return false
+/// on success.
+bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) {
Expr *Fn = TheCall->getCallee();
if (TheCall->getNumArgs() > 2) {
Diag(TheCall->getArg(2)->getLocStart(),
@@ -2321,6 +2475,48 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
return false;
}
+/// Check the arguments to '__builtin_va_start' for validity, and that
+/// it was called from a function of the native ABI.
+/// Emit an error and return true on failure; return false on success.
+bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+ // On x86-64 Unix, don't allow this in Win64 ABI functions.
+ // On x64 Windows, don't allow this in System V ABI functions.
+ // (Yes, that means there's no corresponding way to support variadic
+ // System V ABI functions on Windows.)
+ if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64) {
+ unsigned OS = Context.getTargetInfo().getTriple().getOS();
+ clang::CallingConv CC = CC_C;
+ if (const FunctionDecl *FD = getCurFunctionDecl())
+ CC = FD->getType()->getAs<FunctionType>()->getCallConv();
+ if ((OS == llvm::Triple::Win32 && CC == CC_X86_64SysV) ||
+ (OS != llvm::Triple::Win32 && CC == CC_X86_64Win64))
+ return Diag(TheCall->getCallee()->getLocStart(),
+ diag::err_va_start_used_in_wrong_abi_function)
+ << (OS != llvm::Triple::Win32);
+ }
+ return SemaBuiltinVAStartImpl(TheCall);
+}
+
+/// Check the arguments to '__builtin_ms_va_start' for validity, and that
+/// it was called from a Win64 ABI function.
+/// Emit an error and return true on failure; return false on success.
+bool Sema::SemaBuiltinMSVAStart(CallExpr *TheCall) {
+ // This only makes sense for x86-64.
+ const llvm::Triple &TT = Context.getTargetInfo().getTriple();
+ Expr *Callee = TheCall->getCallee();
+ if (TT.getArch() != llvm::Triple::x86_64)
+ return Diag(Callee->getLocStart(), diag::err_x86_builtin_32_bit_tgt);
+ // Don't allow this in System V ABI functions.
+ clang::CallingConv CC = CC_C;
+ if (const FunctionDecl *FD = getCurFunctionDecl())
+ CC = FD->getType()->getAs<FunctionType>()->getCallConv();
+ if (CC == CC_X86_64SysV ||
+ (TT.getOS() != llvm::Triple::Win32 && CC != CC_X86_64Win64))
+ return Diag(Callee->getLocStart(),
+ diag::err_ms_va_start_used_in_sysv_function);
+ return SemaBuiltinVAStartImpl(TheCall);
+}
+
bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) {
// void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
// const char *named_addr);
@@ -2784,26 +2980,6 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
return false;
}
-/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
-/// This checks that the target supports __builtin_cpu_supports and
-/// that the string argument is constant and valid.
-bool Sema::SemaBuiltinCpuSupports(CallExpr *TheCall) {
- Expr *Arg = TheCall->getArg(0);
-
- // Check if the argument is a string literal.
- if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
- return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
- << Arg->getSourceRange();
-
- // Check the contents of the string.
- StringRef Feature =
- cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
- if (!Context.getTargetInfo().validateCpuSupports(Feature))
- return Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports)
- << Arg->getSourceRange();
- return false;
-}
-
/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
/// This checks that the target supports __builtin_longjmp and
/// that val is a constant 1.
@@ -4833,7 +5009,7 @@ static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range,
}
}
} else {
- FunctionName = S.Context.BuiltinInfo.GetName(AbsKind);
+ FunctionName = S.Context.BuiltinInfo.getName(AbsKind);
HeaderName = S.Context.BuiltinInfo.getHeaderName(AbsKind);
if (HeaderName) {
@@ -4909,7 +5085,7 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
// function call.
if (ArgType->isUnsignedIntegerType()) {
const char *FunctionName =
- IsStdAbs ? "std::abs" : Context.BuiltinInfo.GetName(AbsKind);
+ IsStdAbs ? "std::abs" : Context.BuiltinInfo.getName(AbsKind);
Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
Diag(Call->getExprLoc(), diag::note_remove_abs)
<< FunctionName
@@ -4917,6 +5093,19 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
return;
}
+ // Taking the absolute value of a pointer is very suspicious, they probably
+ // wanted to index into an array, dereference a pointer, call a function, etc.
+ if (ArgType->isPointerType() || ArgType->canDecayToPointerType()) {
+ unsigned DiagType = 0;
+ if (ArgType->isFunctionType())
+ DiagType = 1;
+ else if (ArgType->isArrayType())
+ DiagType = 2;
+
+ Diag(Call->getExprLoc(), diag::warn_pointer_abs) << DiagType << ArgType;
+ return;
+ }
+
// std::abs has overloads which prevent most of the absolute value problems
// from occurring.
if (IsStdAbs)
@@ -5465,17 +5654,15 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
}
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var.
- S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref
- : diag::warn_ret_stack_addr)
+ S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType()
<< DR->getDecl()->getDeclName() << diagRange;
} else if (isa<BlockExpr>(stackE)) { // local block.
S.Diag(diagLoc, diag::err_ret_local_block) << diagRange;
} else if (isa<AddrLabelExpr>(stackE)) { // address of label.
S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
} else { // local temporary.
- S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref
- : diag::warn_ret_local_temp_addr)
- << diagRange;
+ S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref)
+ << lhsType->isReferenceType() << diagRange;
}
// Display the "trail" of reference variables that we followed until we
@@ -5750,6 +5937,11 @@ do {
return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl);
}
+ case Stmt::OMPArraySectionExprClass: {
+ return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars,
+ ParentDecl);
+ }
+
case Stmt::ConditionalOperatorClass: {
// For conditional operators we need to see if either the LHS or RHS are
// non-NULL Expr's. If one is non-NULL, we return it.
@@ -7083,6 +7275,14 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
return;
DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision);
+
+ }
+ // ... or possibly if we're increasing rank, too
+ else if (TargetBT->getKind() > SourceBT->getKind()) {
+ if (S.SourceMgr.isInSystemMacro(CC))
+ return;
+
+ DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_double_promotion);
}
return;
}
@@ -7105,20 +7305,24 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
}
}
- // If the target is bool, warn if expr is a function or method call.
- if (Target->isSpecificBuiltinType(BuiltinType::Bool) &&
- isa<CallExpr>(E)) {
+ // Detect the case where a call result is converted from floating-point to
+ // to bool, and the final argument to the call is converted from bool, to
+ // discover this typo:
+ //
+ // bool b = fabs(x < 1.0); // should be "bool b = fabs(x) < 1.0;"
+ //
+ // FIXME: This is an incredibly special case; is there some more general
+ // way to detect this class of misplaced-parentheses bug?
+ if (Target->isBooleanType() && isa<CallExpr>(E)) {
// Check last argument of function call to see if it is an
// implicit cast from a type matching the type the result
// is being cast to.
CallExpr *CEx = cast<CallExpr>(E);
- unsigned NumArgs = CEx->getNumArgs();
- if (NumArgs > 0) {
+ if (unsigned NumArgs = CEx->getNumArgs()) {
Expr *LastA = CEx->getArg(NumArgs - 1);
Expr *InnerE = LastA->IgnoreParenImpCasts();
- const Type *InnerType =
- S.Context.getCanonicalType(InnerE->getType()).getTypePtr();
- if (isa<ImplicitCastExpr>(LastA) && (InnerType == Target)) {
+ if (isa<ImplicitCastExpr>(LastA) &&
+ InnerE->getType()->isBooleanType()) {
// Warn on this floating-point to bool conversion
DiagnoseImpCast(S, E, T, CC,
diag::warn_impcast_floating_point_to_bool);
@@ -7301,18 +7505,16 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
CheckImplicitConversion(S, E, T, CC);
// Now continue drilling into this expression.
-
- if (PseudoObjectExpr * POE = dyn_cast<PseudoObjectExpr>(E)) {
- if (POE->getResultExpr())
- E = POE->getResultExpr();
- }
-
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
- if (OVE->getSourceExpr())
- AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC);
- return;
+
+ if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
+ // The bound subexpressions in a PseudoObjectExpr are not reachable
+ // as transitive children.
+ // FIXME: Use a more uniform representation for this.
+ for (auto *SE : POE->semantics())
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(SE))
+ AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC);
}
-
+
// Skip past explicit casts.
if (isa<ExplicitCastExpr>(E)) {
E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
@@ -7372,12 +7574,6 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
} // end anonymous namespace
-enum {
- AddressOf,
- FunctionPointer,
- ArrayPointer
-};
-
// Helper function for Sema::DiagnoseAlwaysNonNullPointer.
// Returns true when emitting a warning about taking the address of a reference.
static bool CheckForReference(Sema &SemaRef, const Expr *E,
@@ -7476,6 +7672,26 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
}
}
+ auto ComplainAboutNonnullParamOrCall = [&](bool IsParam) {
+ std::string Str;
+ llvm::raw_string_ostream S(Str);
+ E->printPretty(S, nullptr, getPrintingPolicy());
+ unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare
+ : diag::warn_cast_nonnull_to_bool;
+ Diag(E->getExprLoc(), DiagID) << IsParam << S.str()
+ << E->getSourceRange() << Range << IsEqual;
+ };
+
+ // If we have a CallExpr that is tagged with returns_nonnull, we can complain.
+ if (auto *Call = dyn_cast<CallExpr>(E->IgnoreParenImpCasts())) {
+ if (auto *Callee = Call->getDirectCallee()) {
+ if (Callee->hasAttr<ReturnsNonNullAttr>()) {
+ ComplainAboutNonnullParamOrCall(false);
+ return;
+ }
+ }
+ }
+
// Expect to find a single Decl. Skip anything more complicated.
ValueDecl *D = nullptr;
if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
@@ -7487,40 +7703,38 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
// Weak Decls can be null.
if (!D || D->isWeak())
return;
-
+
// Check for parameter decl with nonnull attribute
- if (const ParmVarDecl* PV = dyn_cast<ParmVarDecl>(D)) {
- if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV))
- if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
- unsigned NumArgs = FD->getNumParams();
- llvm::SmallBitVector AttrNonNull(NumArgs);
+ if (const auto* PV = dyn_cast<ParmVarDecl>(D)) {
+ if (getCurFunction() &&
+ !getCurFunction()->ModifiedNonNullParams.count(PV)) {
+ if (PV->hasAttr<NonNullAttr>()) {
+ ComplainAboutNonnullParamOrCall(true);
+ return;
+ }
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
+ auto ParamIter = std::find(FD->param_begin(), FD->param_end(), PV);
+ assert(ParamIter != FD->param_end());
+ unsigned ParamNo = std::distance(FD->param_begin(), ParamIter);
+
for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
if (!NonNull->args_size()) {
- AttrNonNull.set(0, NumArgs);
- break;
- }
- for (unsigned Val : NonNull->args()) {
- if (Val >= NumArgs)
- continue;
- AttrNonNull.set(Val);
+ ComplainAboutNonnullParamOrCall(true);
+ return;
}
- }
- if (!AttrNonNull.empty())
- for (unsigned i = 0; i < NumArgs; ++i)
- if (FD->getParamDecl(i) == PV &&
- (AttrNonNull[i] || PV->hasAttr<NonNullAttr>())) {
- std::string Str;
- llvm::raw_string_ostream S(Str);
- E->printPretty(S, nullptr, getPrintingPolicy());
- unsigned DiagID = IsCompare ? diag::warn_nonnull_parameter_compare
- : diag::warn_cast_nonnull_to_bool;
- Diag(E->getExprLoc(), DiagID) << S.str() << E->getSourceRange()
- << Range << IsEqual;
+
+ for (unsigned ArgNo : NonNull->args()) {
+ if (ArgNo == ParamNo) {
+ ComplainAboutNonnullParamOrCall(true);
return;
}
+ }
+ }
}
}
-
+ }
+
QualType T = D->getType();
const bool IsArray = T->isArrayType();
const bool IsFunction = T->isFunctionType();
@@ -7541,7 +7755,11 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
: diag::warn_impcast_pointer_to_bool;
- unsigned DiagType;
+ enum {
+ AddressOf,
+ FunctionPointer,
+ ArrayPointer
+ } DiagType;
if (IsAddressOf)
DiagType = AddressOf;
else if (IsFunction)
@@ -8229,6 +8447,15 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
}
}
}
+
+ // Parameters with the pass_object_size attribute only need to be marked
+ // constant at function definitions. Because we lack information about
+ // whether we're on a declaration or definition when we're instantiating the
+ // attribute, we need to check for constness here.
+ if (const auto *Attr = Param->getAttr<PassObjectSizeAttr>())
+ if (!Param->getType().isConstQualified())
+ Diag(Param->getLocation(), diag::err_attribute_pointers_only)
+ << Attr->getSpelling() << 1;
}
return HasInvalidParm;
@@ -8348,7 +8575,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
return;
llvm::APSInt index;
- if (!IndexExpr->EvaluateAsInt(index, Context))
+ if (!IndexExpr->EvaluateAsInt(index, Context, Expr::SE_AllowSideEffects))
return;
if (IndexNegated)
index = -index;
@@ -8462,6 +8689,13 @@ void Sema::CheckArrayAccess(const Expr *expr) {
AllowOnePastEnd > 0);
return;
}
+ case Stmt::OMPArraySectionExprClass: {
+ const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr);
+ if (ASE->getLowerBound())
+ CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(),
+ /*ASE=*/nullptr, AllowOnePastEnd > 0);
+ return;
+ }
case Stmt::UnaryOperatorClass: {
// Only unwrap the * and & unary operators
const UnaryOperator *UO = cast<UnaryOperator>(expr);
@@ -9672,4 +9906,3 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
<< ArgumentExpr->getSourceRange()
<< TypeTagExpr->getSourceRange();
}
-
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 86265275d05e..21cf62585142 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -494,6 +494,7 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
bool &AsNestedNameSpecifier) const {
AsNestedNameSpecifier = false;
+ auto *Named = ND;
ND = ND->getUnderlyingDecl();
// Skip unnamed entities.
@@ -526,14 +527,14 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
return false;
if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
- ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
+ (isa<NamespaceDecl>(ND) &&
Filter != &ResultBuilder::IsNamespace &&
Filter != &ResultBuilder::IsNamespaceOrAlias &&
Filter != nullptr))
AsNestedNameSpecifier = true;
// Filter out any unwanted results.
- if (Filter && !(this->*Filter)(ND)) {
+ if (Filter && !(this->*Filter)(Named)) {
// Check whether it is interesting as a nested-name-specifier.
if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
IsNestedNameSpecifier(ND) &&
@@ -1142,14 +1143,12 @@ bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
/// \brief Determines whether the given declaration is a namespace or
/// namespace alias.
bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
- return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+ return isa<NamespaceDecl>(ND->getUnderlyingDecl());
}
/// \brief Determines whether the given declaration is a type.
bool ResultBuilder::IsType(const NamedDecl *ND) const {
- if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
- ND = Using->getTargetDecl();
-
+ ND = ND->getUnderlyingDecl();
return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
}
@@ -1157,11 +1156,9 @@ bool ResultBuilder::IsType(const NamedDecl *ND) const {
/// "." or "->". Only value declarations, nested name specifiers, and
/// using declarations thereof should show up.
bool ResultBuilder::IsMember(const NamedDecl *ND) const {
- if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
- ND = Using->getTargetDecl();
-
+ ND = ND->getUnderlyingDecl();
return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
- isa<ObjCPropertyDecl>(ND);
+ isa<ObjCPropertyDecl>(ND);
}
static bool isObjCReceiverType(ASTContext &C, QualType T) {
@@ -3036,6 +3033,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
case Decl::ParmVar: return CXCursor_ParmDecl;
case Decl::Typedef: return CXCursor_TypedefDecl;
case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
+ case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
case Decl::Var: return CXCursor_VarDecl;
case Decl::Namespace: return CXCursor_Namespace;
case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
@@ -3376,7 +3374,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
case PCC_Statement:
case PCC_RecoveryInFunction:
if (S->getFnParent())
- AddPrettyFunctionResults(PP.getLangOpts(), Results);
+ AddPrettyFunctionResults(getLangOpts(), Results);
break;
case PCC_Namespace:
@@ -3520,7 +3518,7 @@ void Sema::CodeCompleteExpression(Scope *S,
if (S->getFnParent() &&
!Data.ObjCCollection &&
!Data.IntegralConstantExpression)
- AddPrettyFunctionResults(PP.getLangOpts(), Results);
+ AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
@@ -4051,7 +4049,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
// If expression's type is CXXRecordDecl, it may overload the function
// call operator, so we check if it does and add them as candidates.
// A complete type is needed to lookup for member function call operators.
- if (!RequireCompleteType(Loc, NakedFn->getType(), 0)) {
+ if (isCompleteType(Loc, NakedFn->getType())) {
DeclarationName OpName = Context.DeclarationNames
.getCXXOperatorName(OO_Call);
LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
@@ -4093,7 +4091,7 @@ void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
return;
// A complete type is needed to lookup for constructors.
- if (RequireCompleteType(Loc, Type, 0))
+ if (!isCompleteType(Loc, Type))
return;
CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
@@ -4205,7 +4203,7 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
Results.ExitScope();
if (S->getFnParent())
- AddPrettyFunctionResults(PP.getLangOpts(), Results);
+ AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
@@ -4912,7 +4910,7 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Results.AddResult(CodeCompletionResult("atomic"));
// Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
- if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
+ if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Results.AddResult(CodeCompletionResult("weak"));
@@ -5925,8 +5923,8 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
}
}
-void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
- unsigned NumProtocols) {
+void Sema::CodeCompleteObjCProtocolReferences(
+ ArrayRef<IdentifierLocPair> Protocols) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
@@ -5937,9 +5935,9 @@ void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
// Tell the result set to ignore all of the protocols we have
// already seen.
// FIXME: This doesn't work when caching code-completion results.
- for (unsigned I = 0; I != NumProtocols; ++I)
- if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
- Protocols[I].second))
+ for (const IdentifierLocPair &Pair : Protocols)
+ if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
+ Pair.second))
Results.Ignore(Protocol);
// Add all protocols.
@@ -7079,11 +7077,13 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
// If the result type was not already provided, add it to the
// pattern as (type).
- if (ReturnType.isNull())
- AddObjCPassingTypeChunk(Method->getSendResultType()
- .stripObjCKindOfType(Context),
+ if (ReturnType.isNull()) {
+ QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
+ AttributedType::stripOuterNullability(ResTy);
+ AddObjCPassingTypeChunk(ResTy,
Method->getObjCDeclQualifier(), Context, Policy,
Builder);
+ }
Selector Sel = Method->getSelector();
@@ -7114,6 +7114,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
ParamType = (*P)->getOriginalType();
ParamType = ParamType.substObjCTypeArgs(Context, {},
ObjCSubstitutionContext::Parameter);
+ AttributedType::stripOuterNullability(ParamType);
AddObjCPassingTypeChunk(ParamType,
(*P)->getObjCDeclQualifier(),
Context, Policy,
diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp
new file mode 100644
index 000000000000..4b4fd6b16a06
--- /dev/null
+++ b/lib/Sema/SemaCoroutine.cpp
@@ -0,0 +1,448 @@
+//===--- SemaCoroutines.cpp - Semantic Analysis for Coroutines ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for C++ Coroutines.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Overload.h"
+using namespace clang;
+using namespace sema;
+
+/// Look up the std::coroutine_traits<...>::promise_type for the given
+/// function type.
+static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
+ SourceLocation Loc) {
+ // FIXME: Cache std::coroutine_traits once we've found it.
+ NamespaceDecl *Std = S.getStdNamespace();
+ if (!Std) {
+ S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
+ return QualType();
+ }
+
+ LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
+ Loc, Sema::LookupOrdinaryName);
+ if (!S.LookupQualifiedName(Result, Std)) {
+ S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
+ return QualType();
+ }
+
+ ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
+ if (!CoroTraits) {
+ Result.suppressDiagnostics();
+ // We found something weird. Complain about the first thing we found.
+ NamedDecl *Found = *Result.begin();
+ S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
+ return QualType();
+ }
+
+ // Form template argument list for coroutine_traits<R, P1, P2, ...>.
+ TemplateArgumentListInfo Args(Loc, Loc);
+ Args.addArgument(TemplateArgumentLoc(
+ TemplateArgument(FnType->getReturnType()),
+ S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), Loc)));
+ // FIXME: If the function is a non-static member function, add the type
+ // of the implicit object parameter before the formal parameters.
+ for (QualType T : FnType->getParamTypes())
+ Args.addArgument(TemplateArgumentLoc(
+ TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, Loc)));
+
+ // Build the template-id.
+ QualType CoroTrait =
+ S.CheckTemplateIdType(TemplateName(CoroTraits), Loc, Args);
+ if (CoroTrait.isNull())
+ return QualType();
+ if (S.RequireCompleteType(Loc, CoroTrait,
+ diag::err_coroutine_traits_missing_specialization))
+ return QualType();
+
+ CXXRecordDecl *RD = CoroTrait->getAsCXXRecordDecl();
+ assert(RD && "specialization of class template is not a class?");
+
+ // Look up the ::promise_type member.
+ LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), Loc,
+ Sema::LookupOrdinaryName);
+ S.LookupQualifiedName(R, RD);
+ auto *Promise = R.getAsSingle<TypeDecl>();
+ if (!Promise) {
+ S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found)
+ << RD;
+ return QualType();
+ }
+
+ // The promise type is required to be a class type.
+ QualType PromiseType = S.Context.getTypeDeclType(Promise);
+ if (!PromiseType->getAsCXXRecordDecl()) {
+ // Use the fully-qualified name of the type.
+ auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, Std);
+ NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
+ CoroTrait.getTypePtr());
+ PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
+
+ S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class)
+ << PromiseType;
+ return QualType();
+ }
+
+ return PromiseType;
+}
+
+/// Check that this is a context in which a coroutine suspension can appear.
+static FunctionScopeInfo *
+checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) {
+ // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
+ if (S.isUnevaluatedContext()) {
+ S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
+ return nullptr;
+ }
+
+ // Any other usage must be within a function.
+ // FIXME: Reject a coroutine with a deduced return type.
+ auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
+ if (!FD) {
+ S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
+ ? diag::err_coroutine_objc_method
+ : diag::err_coroutine_outside_function) << Keyword;
+ } else if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) {
+ // Coroutines TS [special]/6:
+ // A special member function shall not be a coroutine.
+ //
+ // FIXME: We assume that this really means that a coroutine cannot
+ // be a constructor or destructor.
+ S.Diag(Loc, diag::err_coroutine_ctor_dtor)
+ << isa<CXXDestructorDecl>(FD) << Keyword;
+ } else if (FD->isConstexpr()) {
+ S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword;
+ } else if (FD->isVariadic()) {
+ S.Diag(Loc, diag::err_coroutine_varargs) << Keyword;
+ } else {
+ auto *ScopeInfo = S.getCurFunction();
+ assert(ScopeInfo && "missing function scope for function");
+
+ // If we don't have a promise variable, build one now.
+ if (!ScopeInfo->CoroutinePromise) {
+ QualType T =
+ FD->getType()->isDependentType()
+ ? S.Context.DependentTy
+ : lookupPromiseType(S, FD->getType()->castAs<FunctionProtoType>(),
+ Loc);
+ if (T.isNull())
+ return nullptr;
+
+ // Create and default-initialize the promise.
+ ScopeInfo->CoroutinePromise =
+ VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(),
+ &S.PP.getIdentifierTable().get("__promise"), T,
+ S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
+ S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
+ if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
+ S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false);
+ }
+
+ return ScopeInfo;
+ }
+
+ return nullptr;
+}
+
+/// Build a call to 'operator co_await' if there is a suitable operator for
+/// the given expression.
+static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
+ SourceLocation Loc, Expr *E) {
+ UnresolvedSet<16> Functions;
+ SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(),
+ Functions);
+ return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
+}
+
+struct ReadySuspendResumeResult {
+ bool IsInvalid;
+ Expr *Results[3];
+};
+
+static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
+ StringRef Name,
+ MutableArrayRef<Expr *> Args) {
+ DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
+
+ // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
+ CXXScopeSpec SS;
+ ExprResult Result = S.BuildMemberReferenceExpr(
+ Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
+ SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
+ /*Scope=*/nullptr);
+ if (Result.isInvalid())
+ return ExprError();
+
+ return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
+}
+
+/// Build calls to await_ready, await_suspend, and await_resume for a co_await
+/// expression.
+static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
+ Expr *E) {
+ // Assume invalid until we see otherwise.
+ ReadySuspendResumeResult Calls = {true, {}};
+
+ const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
+ for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
+ Expr *Operand = new (S.Context) OpaqueValueExpr(
+ Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
+
+ // FIXME: Pass coroutine handle to await_suspend.
+ ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
+ if (Result.isInvalid())
+ return Calls;
+ Calls.Results[I] = Result.get();
+ }
+
+ Calls.IsInvalid = false;
+ return Calls;
+}
+
+ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
+ if (E->getType()->isPlaceholderType()) {
+ ExprResult R = CheckPlaceholderExpr(E);
+ if (R.isInvalid()) return ExprError();
+ E = R.get();
+ }
+
+ ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
+ if (Awaitable.isInvalid())
+ return ExprError();
+ return BuildCoawaitExpr(Loc, Awaitable.get());
+}
+ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
+ if (!Coroutine)
+ return ExprError();
+
+ if (E->getType()->isPlaceholderType()) {
+ ExprResult R = CheckPlaceholderExpr(E);
+ if (R.isInvalid()) return ExprError();
+ E = R.get();
+ }
+
+ if (E->getType()->isDependentType()) {
+ Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+ }
+
+ // If the expression is a temporary, materialize it as an lvalue so that we
+ // can use it multiple times.
+ if (E->getValueKind() == VK_RValue)
+ E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
+
+ // Build the await_ready, await_suspend, await_resume calls.
+ ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
+ if (RSS.IsInvalid)
+ return ExprError();
+
+ Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
+ RSS.Results[2]);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+}
+
+static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine,
+ SourceLocation Loc, StringRef Name,
+ MutableArrayRef<Expr *> Args) {
+ assert(Coroutine->CoroutinePromise && "no promise for coroutine");
+
+ // Form a reference to the promise.
+ auto *Promise = Coroutine->CoroutinePromise;
+ ExprResult PromiseRef = S.BuildDeclRefExpr(
+ Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
+ if (PromiseRef.isInvalid())
+ return ExprError();
+
+ // Call 'yield_value', passing in E.
+ return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
+}
+
+ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
+ if (!Coroutine)
+ return ExprError();
+
+ // Build yield_value call.
+ ExprResult Awaitable =
+ buildPromiseCall(*this, Coroutine, Loc, "yield_value", E);
+ if (Awaitable.isInvalid())
+ return ExprError();
+
+ // Build 'operator co_await' call.
+ Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
+ if (Awaitable.isInvalid())
+ return ExprError();
+
+ return BuildCoyieldExpr(Loc, Awaitable.get());
+}
+ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
+ if (!Coroutine)
+ return ExprError();
+
+ if (E->getType()->isPlaceholderType()) {
+ ExprResult R = CheckPlaceholderExpr(E);
+ if (R.isInvalid()) return ExprError();
+ E = R.get();
+ }
+
+ if (E->getType()->isDependentType()) {
+ Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+ }
+
+ // If the expression is a temporary, materialize it as an lvalue so that we
+ // can use it multiple times.
+ if (E->getValueKind() == VK_RValue)
+ E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
+
+ // Build the await_ready, await_suspend, await_resume calls.
+ ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
+ if (RSS.IsInvalid)
+ return ExprError();
+
+ Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
+ RSS.Results[2]);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+}
+
+StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
+ return BuildCoreturnStmt(Loc, E);
+}
+StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
+ if (!Coroutine)
+ return StmtError();
+
+ if (E && E->getType()->isPlaceholderType() &&
+ !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
+ ExprResult R = CheckPlaceholderExpr(E);
+ if (R.isInvalid()) return StmtError();
+ E = R.get();
+ }
+
+ // FIXME: If the operand is a reference to a variable that's about to go out
+ // of scope, we should treat the operand as an xvalue for this overload
+ // resolution.
+ ExprResult PC;
+ if (E && !E->getType()->isVoidType()) {
+ PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E);
+ } else {
+ E = MakeFullDiscardedValueExpr(E).get();
+ PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None);
+ }
+ if (PC.isInvalid())
+ return StmtError();
+
+ Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
+
+ Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+}
+
+void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
+ FunctionScopeInfo *Fn = getCurFunction();
+ assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
+
+ // Coroutines [stmt.return]p1:
+ // A return statement shall not appear in a coroutine.
+ if (Fn->FirstReturnLoc.isValid()) {
+ Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
+ auto *First = Fn->CoroutineStmts[0];
+ Diag(First->getLocStart(), diag::note_declared_coroutine_here)
+ << (isa<CoawaitExpr>(First) ? 0 :
+ isa<CoyieldExpr>(First) ? 1 : 2);
+ }
+
+ bool AnyCoawaits = false;
+ bool AnyCoyields = false;
+ for (auto *CoroutineStmt : Fn->CoroutineStmts) {
+ AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt);
+ AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt);
+ }
+
+ if (!AnyCoawaits && !AnyCoyields)
+ Diag(Fn->CoroutineStmts.front()->getLocStart(),
+ diag::ext_coroutine_without_co_await_co_yield);
+
+ SourceLocation Loc = FD->getLocation();
+
+ // Form a declaration statement for the promise declaration, so that AST
+ // visitors can more easily find it.
+ StmtResult PromiseStmt =
+ ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc);
+ if (PromiseStmt.isInvalid())
+ return FD->setInvalidDecl();
+
+ // Form and check implicit 'co_await p.initial_suspend();' statement.
+ ExprResult InitialSuspend =
+ buildPromiseCall(*this, Fn, Loc, "initial_suspend", None);
+ // FIXME: Support operator co_await here.
+ if (!InitialSuspend.isInvalid())
+ InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get());
+ InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get());
+ if (InitialSuspend.isInvalid())
+ return FD->setInvalidDecl();
+
+ // Form and check implicit 'co_await p.final_suspend();' statement.
+ ExprResult FinalSuspend =
+ buildPromiseCall(*this, Fn, Loc, "final_suspend", None);
+ // FIXME: Support operator co_await here.
+ if (!FinalSuspend.isInvalid())
+ FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get());
+ FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get());
+ if (FinalSuspend.isInvalid())
+ return FD->setInvalidDecl();
+
+ // FIXME: Perform analysis of set_exception call.
+
+ // FIXME: Try to form 'p.return_void();' expression statement to handle
+ // control flowing off the end of the coroutine.
+
+ // Build implicit 'p.get_return_object()' expression and form initialization
+ // of return type from it.
+ ExprResult ReturnObject =
+ buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
+ if (ReturnObject.isInvalid())
+ return FD->setInvalidDecl();
+ QualType RetType = FD->getReturnType();
+ if (!RetType->isDependentType()) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeResult(Loc, RetType, false);
+ ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
+ ReturnObject.get());
+ if (ReturnObject.isInvalid())
+ return FD->setInvalidDecl();
+ }
+ ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc);
+ if (ReturnObject.isInvalid())
+ return FD->setInvalidDecl();
+
+ // FIXME: Perform move-initialization of parameters into frame-local copies.
+ SmallVector<Expr*, 16> ParamMoves;
+
+ // Build body for the coroutine wrapper statement.
+ Body = new (Context) CoroutineBodyStmt(
+ Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(),
+ /*SetException*/nullptr, /*Fallthrough*/nullptr,
+ ReturnObject.get(), ParamMoves);
+}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c694a20319b0..2c5516a48d64 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -33,7 +33,6 @@
#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
#include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex
#include "clang/Lex/Preprocessor.h" // Included for isCodeCompletionEnabled()
-#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
@@ -111,6 +110,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw_wchar_t:
case tok::kw_bool:
case tok::kw___underlying_type:
+ case tok::kw___auto_type:
return true;
case tok::annot_typename:
@@ -795,7 +795,7 @@ Corrected:
}
// In C, we first see whether there is a tag type by the same name, in
- // which case it's likely that the user just forget to write "enum",
+ // which case it's likely that the user just forgot to write "enum",
// "struct", or "union".
if (!getLangOpts().CPlusPlus && !SecondTry &&
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
@@ -813,9 +813,8 @@ Corrected:
unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
unsigned QualifiedDiag = diag::err_no_member_suggest;
- NamedDecl *FirstDecl = Corrected.getCorrectionDecl();
- NamedDecl *UnderlyingFirstDecl
- = FirstDecl? FirstDecl->getUnderlyingDecl() : nullptr;
+ NamedDecl *FirstDecl = Corrected.getFoundDecl();
+ NamedDecl *UnderlyingFirstDecl = Corrected.getCorrectionDecl();
if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
UnqualifiedDiag = diag::err_no_template_suggest;
@@ -1022,7 +1021,7 @@ Corrected:
if (FirstDecl->isCXXClassMember())
return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result,
- nullptr);
+ nullptr, S);
bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
return BuildDeclarationNameExpr(SS, Result, ADL);
@@ -1089,7 +1088,9 @@ Sema::SkippedDefinitionContext Sema::ActOnTagStartSkippedDefinition(Scope *S,
auto Result = static_cast<SkippedDefinitionContext>(CurContext);
CurContext = cast<TagDecl>(D)->getDefinition();
assert(CurContext && "skipping definition of undefined tag");
- S->setEntity(CurContext);
+ // Start lookups from the parent of the current context; we don't want to look
+ // into the pre-existing complete definition.
+ S->setEntity(CurContext->getLookupParent());
return Result;
}
@@ -1733,20 +1734,18 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
if (Error) {
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_sysheader)
- << getHeaderName(Error)
- << Context.BuiltinInfo.GetName(ID);
+ << getHeaderName(Error) << Context.BuiltinInfo.getName(ID);
return nullptr;
}
if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(ID)) {
Diag(Loc, diag::ext_implicit_lib_function_decl)
- << Context.BuiltinInfo.GetName(ID)
- << R;
+ << Context.BuiltinInfo.getName(ID) << R;
if (Context.BuiltinInfo.getHeaderName(ID) &&
!Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc))
Diag(Loc, diag::note_include_header_or_declare)
<< Context.BuiltinInfo.getHeaderName(ID)
- << Context.BuiltinInfo.GetName(ID);
+ << Context.BuiltinInfo.getName(ID);
}
DeclContext *Parent = Context.getTranslationUnitDecl();
@@ -1796,37 +1795,6 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
return New;
}
-/// \brief Filter out any previous declarations that the given declaration
-/// should not consider because they are not permitted to conflict, e.g.,
-/// because they come from hidden sub-modules and do not refer to the same
-/// entity.
-static void filterNonConflictingPreviousDecls(Sema &S,
- NamedDecl *decl,
- LookupResult &previous){
- // This is only interesting when modules are enabled.
- if ((!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) ||
- !S.getLangOpts().ModulesHideInternalLinkage)
- return;
-
- // Empty sets are uninteresting.
- if (previous.empty())
- return;
-
- LookupResult::Filter filter = previous.makeFilter();
- while (filter.hasNext()) {
- NamedDecl *old = filter.next();
-
- // Non-hidden declarations are never ignored.
- if (S.isVisible(old))
- continue;
-
- if (!old->isExternallyVisible())
- filter.erase();
- }
-
- filter.done();
-}
-
/// Typedef declarations don't have linkage, but they still denote the same
/// entity if their types are the same.
/// FIXME: This is notionally doing the same thing as ASTReaderDecl's
@@ -1859,13 +1827,13 @@ static void filterNonConflictingPreviousTypedefDecls(Sema &S,
// If both declarations give a tag declaration a typedef name for linkage
// purposes, then they declare the same entity.
- if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) &&
+ if (S.getLangOpts().CPlusPlus &&
+ OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) &&
Decl->getAnonDeclWithTypedefName())
continue;
}
- if (!Old->isExternallyVisible())
- Filter.erase();
+ Filter.erase();
}
Filter.done();
@@ -1910,7 +1878,8 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
/// how to resolve this situation, merging decls or emitting
/// diagnostics as appropriate. If there was an error, set New to be invalid.
///
-void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
+void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
+ LookupResult &OldDecls) {
// If the new decl is known invalid already, don't bother doing any
// merging checks.
if (New->isInvalidDecl()) return;
@@ -1991,6 +1960,19 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
// Make the old tag definition visible.
makeMergedDefinitionVisible(Hidden, NewTag->getLocation());
+
+ // If this was an unscoped enumeration, yank all of its enumerators
+ // out of the scope.
+ if (isa<EnumDecl>(NewTag)) {
+ Scope *EnumScope = getNonFieldDeclScope(S);
+ for (auto *D : NewTag->decls()) {
+ auto *ED = cast<EnumConstantDecl>(D);
+ assert(EnumScope->isDeclScope(ED));
+ EnumScope->RemoveDecl(ED);
+ IdResolver.RemoveDecl(ED);
+ ED->getLexicalDeclContext()->removeDecl(ED);
+ }
+ }
}
}
@@ -2206,14 +2188,15 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
}
static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
- const InheritableAttr *Attr, bool Override) {
+ const InheritableAttr *Attr,
+ Sema::AvailabilityMergeKind AMK) {
InheritableAttr *NewAttr = nullptr;
unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr))
NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
AA->getIntroduced(), AA->getDeprecated(),
AA->getObsoleted(), AA->getUnavailable(),
- AA->getMessage(), Override,
+ AA->getMessage(), AMK,
AttrSpellingListIndex);
else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr))
NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
@@ -2246,11 +2229,22 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex);
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex);
+ else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
+ NewAttr = S.mergeInternalLinkageAttr(
+ D, InternalLinkageA->getRange(),
+ &S.Context.Idents.get(InternalLinkageA->getSpelling()),
+ AttrSpellingListIndex);
+ else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr))
+ NewAttr = S.mergeCommonAttr(D, CommonA->getRange(),
+ &S.Context.Idents.get(CommonA->getSpelling()),
+ AttrSpellingListIndex);
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
NewAttr = nullptr;
- else if (isa<DeprecatedAttr>(Attr) && Override)
+ else if ((isa<DeprecatedAttr>(Attr) || isa<UnavailableAttr>(Attr)) &&
+ (AMK == Sema::AMK_Override ||
+ AMK == Sema::AMK_ProtocolImplementation))
NewAttr = nullptr;
else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
@@ -2303,9 +2297,17 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
const Attr *NewAttribute = NewAttributes[I];
if (isa<AliasAttr>(NewAttribute)) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New))
- S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def));
- else {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) {
+ Sema::SkipBodyInfo SkipBody;
+ S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def), &SkipBody);
+
+ // If we're skipping this definition, drop the "alias" attribute.
+ if (SkipBody.ShouldSkip) {
+ NewAttributes.erase(NewAttributes.begin() + I);
+ --E;
+ continue;
+ }
+ } else {
VarDecl *VD = cast<VarDecl>(New);
unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() ==
VarDecl::TentativeDefinition
@@ -2376,9 +2378,24 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (!Old->hasAttrs() && !New->hasAttrs())
return;
- // attributes declared post-definition are currently ignored
+ // Attributes declared post-definition are currently ignored.
checkNewAttributesAfterDef(*this, New, Old);
+ if (AsmLabelAttr *NewA = New->getAttr<AsmLabelAttr>()) {
+ if (AsmLabelAttr *OldA = Old->getAttr<AsmLabelAttr>()) {
+ if (OldA->getLabel() != NewA->getLabel()) {
+ // This redeclaration changes __asm__ label.
+ Diag(New->getLocation(), diag::err_different_asm_label);
+ Diag(OldA->getLocation(), diag::note_previous_declaration);
+ }
+ } else if (Old->isUsed()) {
+ // This redeclaration adds an __asm__ label to a declaration that has
+ // already been ODR-used.
+ Diag(New->getLocation(), diag::err_late_asm_label_name)
+ << isa<FunctionDecl>(Old) << New->getAttr<AsmLabelAttr>()->getRange();
+ }
+ }
+
if (!Old->hasAttrs())
return;
@@ -2389,8 +2406,8 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (!foundAny) New->setAttrs(AttrVec());
for (auto *I : Old->specific_attrs<InheritableAttr>()) {
- bool Override = false;
// Ignore deprecated/unavailable/availability attributes if requested.
+ AvailabilityMergeKind LocalAMK = AMK_None;
if (isa<DeprecatedAttr>(I) ||
isa<UnavailableAttr>(I) ||
isa<AvailabilityAttr>(I)) {
@@ -2399,10 +2416,9 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
continue;
case AMK_Redeclaration:
- break;
-
case AMK_Override:
- Override = true;
+ case AMK_ProtocolImplementation:
+ LocalAMK = AMK;
break;
}
}
@@ -2411,7 +2427,7 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (isa<UsedAttr>(I))
continue;
- if (mergeDeclAttribute(*this, New, I, Override))
+ if (mergeDeclAttribute(*this, New, I, LocalAMK))
foundAny = true;
}
@@ -2619,6 +2635,21 @@ static bool checkUsingShadowRedecl(Sema &S, UsingShadowDecl *OldS,
return false;
}
+static bool hasIdenticalPassObjectSizeAttrs(const FunctionDecl *A,
+ const FunctionDecl *B) {
+ assert(A->getNumParams() == B->getNumParams());
+
+ auto AttrEq = [](const ParmVarDecl *A, const ParmVarDecl *B) {
+ const auto *AttrA = A->getAttr<PassObjectSizeAttr>();
+ const auto *AttrB = B->getAttr<PassObjectSizeAttr>();
+ if (AttrA == AttrB)
+ return true;
+ return AttrA && AttrB && AttrA->getType() == AttrB->getType();
+ };
+
+ return std::equal(A->param_begin(), A->param_end(), B->param_begin(), AttrEq);
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -2685,6 +2716,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
}
}
+ if (New->hasAttr<InternalLinkageAttr>() &&
+ !Old->hasAttr<InternalLinkageAttr>()) {
+ Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ New->dropAttr<InternalLinkageAttr>();
+ }
// If a function is first declared with a calling convention, but is later
// declared or defined without one, all following decls assume the calling
@@ -2790,7 +2828,17 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
Old->isInlined() && !Old->hasAttr<GNUInlineAttr>()) {
UndefinedButUsed.erase(Old->getCanonicalDecl());
}
-
+
+ // If pass_object_size params don't match up perfectly, this isn't a valid
+ // redeclaration.
+ if (Old->getNumParams() > 0 && Old->getNumParams() == New->getNumParams() &&
+ !hasIdenticalPassObjectSizeAttrs(Old, New)) {
+ Diag(New->getLocation(), diag::err_different_pass_object_size_params)
+ << New->getDeclName();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
+ return true;
+ }
+
if (getLangOpts().CPlusPlus) {
// (C++98 13.1p2):
// Certain function declarations cannot be overloaded:
@@ -3115,7 +3163,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// remain visible, a single bogus local redeclaration (which is
// actually only a warning) could break all the downstream code.
if (!New->getLexicalDeclContext()->isFunctionOrMethod())
- New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
+ New->getIdentifier()->revertBuiltin();
return false;
}
@@ -3179,8 +3227,11 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
// Merge the attributes, including deprecated/unavailable
AvailabilityMergeKind MergeKind =
- isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
- : AMK_Override;
+ isa<ObjCProtocolDecl>(oldMethod->getDeclContext())
+ ? AMK_ProtocolImplementation
+ : isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
+ : AMK_Override;
+
mergeDeclAttributes(newMethod, oldMethod, MergeKind);
// Merge attributes from the parameters.
@@ -3331,6 +3382,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (New->isInvalidDecl())
return;
+ if (!shouldLinkPossiblyHiddenDecl(Previous, New))
+ return;
+
VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate();
// Verify the old decl was also a variable or variable template.
@@ -3362,15 +3416,12 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return New->setInvalidDecl();
}
- if (!shouldLinkPossiblyHiddenDecl(Old, New))
- return;
-
// Ensure the template parameters are compatible.
if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
- return;
+ return New->setInvalidDecl();
// C++ [class.mem]p1:
// A member shall not be declared twice in the member-specification [...]
@@ -3395,6 +3446,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->dropAttr<WeakImportAttr>();
}
+ if (New->hasAttr<InternalLinkageAttr>() &&
+ !Old->hasAttr<InternalLinkageAttr>()) {
+ Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ New->dropAttr<InternalLinkageAttr>();
+ }
+
// Merge the types.
VarDecl *MostRecent = Old->getMostRecentDecl();
if (MostRecent != Old) {
@@ -3583,11 +3642,11 @@ void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) {
void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
TypedefNameDecl *NewTD) {
- // Do nothing if the tag is not anonymous or already has an
- // associated typedef (from an earlier typedef in this decl group).
- if (TagFromDeclSpec->getIdentifier())
+ if (TagFromDeclSpec->isInvalidDecl())
return;
- if (TagFromDeclSpec->getTypedefNameForAnonDecl())
+
+ // Do nothing if the tag already has a name for linkage purposes.
+ if (TagFromDeclSpec->hasNameForLinkage())
return;
// A well-formed anonymous tag must always be a TUK_Definition.
@@ -3595,8 +3654,11 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
// The type must match the tag exactly; no qualifiers allowed.
if (!Context.hasSameType(NewTD->getUnderlyingType(),
- Context.getTagDeclType(TagFromDeclSpec)))
+ Context.getTagDeclType(TagFromDeclSpec))) {
+ if (getLangOpts().CPlusPlus)
+ Context.addTypedefNameForUnnamedTagDecl(TagFromDeclSpec, NewTD);
return;
+ }
// If we've already computed linkage for the anonymous tag, then
// adding a typedef name for the anonymous decl can change that
@@ -3695,6 +3757,14 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return TagD;
}
+ if (DS.isConceptSpecified()) {
+ // C++ Concepts TS [dcl.spec.concept]p1: A concept definition refers to
+ // either a function concept and its definition or a variable concept and
+ // its initializer.
+ Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind);
+ return TagD;
+ }
+
DiagnoseFunctionSpecifiers(DS);
if (DS.isFriendSpecified()) {
@@ -3709,10 +3779,15 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
bool IsExplicitSpecialization =
!TemplateParams.empty() && TemplateParams.back()->size() == 0;
if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
- !IsExplicitInstantiation && !IsExplicitSpecialization) {
+ !IsExplicitInstantiation && !IsExplicitSpecialization &&
+ !isa<ClassTemplatePartialSpecializationDecl>(Tag)) {
// Per C++ [dcl.type.elab]p1, a class declaration cannot have a
// nested-name-specifier unless it is an explicit instantiation
// or an explicit specialization.
+ //
+ // FIXME: We allow class template partial specializations here too, per the
+ // obvious intent of DR1819.
+ //
// Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
<< GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
@@ -3882,7 +3957,7 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
DeclContext *Owner,
DeclarationName Name,
SourceLocation NameLoc,
- unsigned diagnostic) {
+ bool IsUnion) {
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
Sema::ForRedeclaration);
if (!SemaRef.LookupName(R, S)) return false;
@@ -3897,7 +3972,8 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
if (!SemaRef.isDeclInScope(PrevDecl, Owner, S))
return false;
- SemaRef.Diag(NameLoc, diagnostic) << Name;
+ SemaRef.Diag(NameLoc, diag::err_anonymous_record_member_redecl)
+ << IsUnion << Name;
SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
return true;
@@ -3925,10 +4001,6 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
AccessSpecifier AS,
SmallVectorImpl<NamedDecl *> &Chaining,
bool MSAnonStruct) {
- unsigned diagKind
- = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
- : diag::err_anonymous_struct_member_redecl;
-
bool Invalid = false;
// Look every FieldDecl and IndirectFieldDecl with a name.
@@ -3937,7 +4009,8 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
cast<NamedDecl>(D)->getDeclName()) {
ValueDecl *VD = cast<ValueDecl>(D);
if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(),
- VD->getLocation(), diagKind)) {
+ VD->getLocation(),
+ AnonRecord->isUnion())) {
// C++ [class.union]p2:
// The names of the members of an anonymous union shall be
// distinct from the names of any other entity in the
@@ -4131,7 +4204,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
assert(FD->getAccess() != AS_none);
if (FD->getAccess() != AS_public) {
Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member)
- << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
+ << Record->isUnion() << (FD->getAccess() == AS_protected);
Invalid = true;
}
@@ -4155,11 +4228,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// Visual C++ allows type definition in anonymous struct or union.
if (getLangOpts().MicrosoftExt)
Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type)
- << (int)Record->isUnion();
+ << Record->isUnion();
else {
// This is a nested type declaration.
Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type)
- << (int)Record->isUnion();
+ << Record->isUnion();
Invalid = true;
}
} else {
@@ -4168,7 +4241,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// not part of standard C++.
Diag(MemRecord->getLocation(),
diag::ext_anonymous_record_with_anonymous_type)
- << (int)Record->isUnion();
+ << Record->isUnion();
}
} else if (isa<AccessSpecDecl>(Mem)) {
// Any access specifier is fine.
@@ -4189,10 +4262,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (getLangOpts().MicrosoftExt &&
DK == diag::err_anonymous_record_with_type)
Diag(Mem->getLocation(), diag::ext_anonymous_record_with_type)
- << (int)Record->isUnion();
+ << Record->isUnion();
else {
- Diag(Mem->getLocation(), DK)
- << (int)Record->isUnion();
+ Diag(Mem->getLocation(), DK) << Record->isUnion();
Invalid = true;
}
}
@@ -4209,7 +4281,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (!Record->isUnion() && !Owner->isRecord()) {
Diag(Record->getLocation(), diag::err_anonymous_struct_not_member)
- << (int)getLangOpts().CPlusPlus;
+ << getLangOpts().CPlusPlus;
Invalid = true;
}
@@ -4885,6 +4957,23 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
if (getLangOpts().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
+ if (D.getDeclSpec().isConceptSpecified()) {
+ // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+ // applied only to the definition of a function template or variable
+ // template, declared in namespace scope
+ if (!TemplateParamLists.size()) {
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag:: err_concept_wrong_decl_kind);
+ return nullptr;
+ }
+
+ if (!DC->getRedeclContext()->isFileContext()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_concept_decls_may_only_appear_in_namespace_scope);
+ return nullptr;
+ }
+ }
+
NamedDecl *New;
bool AddToScope = true;
@@ -5102,6 +5191,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getDeclSpec().isConstexprSpecified())
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 1;
+ if (D.getDeclSpec().isConceptSpecified())
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag::err_concept_wrong_decl_kind);
if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
Diag(D.getName().StartLocation, diag::err_typedef_not_identifier)
@@ -5174,7 +5266,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
filterNonConflictingPreviousTypedefDecls(*this, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
- MergeTypedefNameDecl(NewTD, Previous);
+ MergeTypedefNameDecl(S, NewTD, Previous);
}
// If this is the C FILE type, notify the AST context.
@@ -5343,14 +5435,26 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
}
}
- // dll attributes require external linkage.
if (const InheritableAttr *Attr = getDLLAttr(&ND)) {
- if (!ND.isExternallyVisible()) {
+ // dll attributes require external linkage. Static locals may have external
+ // linkage but still cannot be explicitly imported or exported.
+ auto *VD = dyn_cast<VarDecl>(&ND);
+ if (!ND.isExternallyVisible() || (VD && VD->isStaticLocal())) {
S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
<< &ND << Attr;
ND.setInvalidDecl();
}
}
+
+ // Virtual functions cannot be marked as 'notail'.
+ if (auto *Attr = ND.getAttr<NotTailCalledAttr>())
+ if (auto *MD = dyn_cast<CXXMethodDecl>(&ND))
+ if (MD->isVirtual()) {
+ S.Diag(ND.getLocation(),
+ diag::err_invalid_attribute_on_virtual_function)
+ << Attr;
+ ND.dropAttr<NotTailCalledAttr>();
+ }
}
static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
@@ -5501,6 +5605,12 @@ static bool isIncompleteDeclExternC(Sema &S, const T *D) {
// In C++, the overloadable attribute negates the effects of extern "C".
if (!D->isInExternCContext() || D->template hasAttr<OverloadableAttr>())
return false;
+
+ // So do CUDA's host/device attributes if overloading is enabled.
+ if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads &&
+ (D->template hasAttr<CUDADeviceAttr>() ||
+ D->template hasAttr<CUDAHostAttr>()))
+ return false;
}
return D->isExternC();
}
@@ -5574,15 +5684,12 @@ bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
return true;
}
-/// \brief Returns true if given declaration is TU-scoped and externally
-/// visible.
-static bool isDeclTUScopedExternallyVisible(const Decl *D) {
- if (auto *FD = dyn_cast<FunctionDecl>(D))
- return (FD->getDeclContext()->isTranslationUnit() || FD->isExternC()) &&
- FD->hasExternalFormalLinkage();
- else if (auto *VD = dyn_cast<VarDecl>(D))
- return (VD->getDeclContext()->isTranslationUnit() || VD->isExternC()) &&
- VD->hasExternalFormalLinkage();
+/// \brief Returns true if given declaration has external C language linkage.
+static bool isDeclExternC(const Decl *D) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ return FD->isExternC();
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ return VD->isExternC();
llvm_unreachable("Unknown type of decl!");
}
@@ -5646,7 +5753,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Suppress the warning in system macros, it's used in macros in some
// popular C system headers, such as in glibc's htonl() macro.
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
- diag::warn_deprecated_register)
+ getLangOpts().CPlusPlus1z ? diag::ext_register_storage_class
+ : diag::warn_deprecated_register)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
}
@@ -5670,12 +5778,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
if (getLangOpts().OpenCL) {
- // Set up the special work-group-local storage class for variables in the
- // OpenCL __local address space.
- if (R.getAddressSpace() == LangAS::opencl_local) {
- SC = SC_OpenCLWorkGroupLocal;
- }
-
// OpenCL v1.2 s6.9.b p4:
// The sampler type cannot be used with the __local and __global address
// space qualifiers.
@@ -5712,7 +5814,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
R, TInfo, SC);
-
+
+ if (D.getDeclSpec().containsPlaceholderType() && R->getContainedAutoType())
+ ParsingInitForAutoVars.insert(NewVD);
+
if (D.isInvalidType())
NewVD->setInvalidDecl();
} else {
@@ -5742,8 +5847,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
break;
case SC_PrivateExtern:
llvm_unreachable("C storage class in c++!");
- case SC_OpenCLWorkGroupLocal:
- llvm_unreachable("OpenCL storage class in c++!");
}
}
@@ -5860,11 +5963,31 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
unsigned VDTemplateParamLists = TemplateParams ? 1 : 0;
if (TemplateParamLists.size() > VDTemplateParamLists)
NewVD->setTemplateParameterListsInfo(
- Context, TemplateParamLists.size() - VDTemplateParamLists,
- TemplateParamLists.data());
+ Context, TemplateParamLists.drop_back(VDTemplateParamLists));
if (D.getDeclSpec().isConstexprSpecified())
NewVD->setConstexpr(true);
+
+ if (D.getDeclSpec().isConceptSpecified()) {
+ NewVD->setConcept(true);
+
+ // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
+ // be declared with the thread_local, inline, friend, or constexpr
+ // specifiers, [...]
+ if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) {
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 0 << 0;
+ NewVD->setInvalidDecl(true);
+ }
+
+ if (D.getDeclSpec().isConstexprSpecified()) {
+ Diag(D.getDeclSpec().getConstexprSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 0 << 3;
+ NewVD->setInvalidDecl(true);
+ }
+ }
}
// Set the lexical context. If the declarator has a C++ scope specifier, the
@@ -5990,19 +6113,31 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
break;
case SC_Register:
// Local Named register
- if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
+ if (!Context.getTargetInfo().isValidGCCRegisterName(Label) &&
+ DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl()))
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
break;
case SC_Static:
case SC_Extern:
case SC_PrivateExtern:
- case SC_OpenCLWorkGroupLocal:
break;
}
} else if (SC == SC_Register) {
// Global Named register
- if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
- Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+ if (DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) {
+ const auto &TI = Context.getTargetInfo();
+ bool HasSizeMismatch;
+
+ if (!TI.isValidGCCRegisterName(Label))
+ Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+ else if (!TI.validateGlobalRegisterVariable(Label,
+ Context.getTypeSize(R),
+ HasSizeMismatch))
+ Diag(E->getExprLoc(), diag::err_asm_invalid_global_var_reg) << Label;
+ else if (HasSizeMismatch)
+ Diag(E->getExprLoc(), diag::err_asm_register_size_mismatch) << Label;
+ }
+
if (!R->isIntegralType(Context) && !R->isPointerType()) {
Diag(D.getLocStart(), diag::err_asm_bad_register_type);
NewVD->setInvalidDecl(true);
@@ -6011,13 +6146,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
Context, Label, 0));
- } else if (!ExtnameUndeclaredIdentifiers.empty() &&
- isDeclTUScopedExternallyVisible(NewVD)) {
+ } else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
- NewVD->addAttr(I->second);
- ExtnameUndeclaredIdentifiers.erase(I);
+ if (isDeclExternC(NewVD)) {
+ NewVD->addAttr(I->second);
+ ExtnameUndeclaredIdentifiers.erase(I);
+ } else
+ Diag(NewVD->getLocation(), diag::warn_redefine_extname_not_applied)
+ << /*Variable*/1 << NewVD;
}
}
@@ -6118,6 +6256,22 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ // Special handling of variable named 'main'.
+ if (Name.isIdentifier() && Name.getAsIdentifierInfo()->isStr("main") &&
+ NewVD->getDeclContext()->getRedeclContext()->isTranslationUnit() &&
+ !getLangOpts().Freestanding && !NewVD->getDescribedVarTemplate()) {
+
+ // C++ [basic.start.main]p3
+ // A program that declares a variable main at global scope is ill-formed.
+ if (getLangOpts().CPlusPlus)
+ Diag(D.getLocStart(), diag::err_main_global_variable);
+
+ // In C, and external-linkage variable named main results in undefined
+ // behavior.
+ else if (NewVD->hasExternalFormalLinkage())
+ Diag(D.getLocStart(), diag::warn_main_redefined);
+ }
+
if (D.isRedeclaration() && !Previous.empty()) {
checkDLLAttributeRedeclaration(
*this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
@@ -6370,31 +6524,79 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
// This includes arrays of objects with address space qualifiers, but not
// automatic variables that point to other address spaces.
// ISO/IEC TR 18037 S5.1.2
- if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
+ if (!getLangOpts().OpenCL
+ && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
NewVD->setInvalidDecl();
return;
}
- // OpenCL v1.2 s6.5 - All program scope variables must be declared in the
- // __constant address space.
- if (getLangOpts().OpenCL && NewVD->isFileVarDecl()
- && T.getAddressSpace() != LangAS::opencl_constant
- && !T->isSamplerT()){
- Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space);
- NewVD->setInvalidDecl();
- return;
- }
-
// OpenCL v1.2 s6.8 -- The static qualifier is valid only in program
// scope.
- if ((getLangOpts().OpenCLVersion >= 120)
- && NewVD->isStaticLocal()) {
+ if (getLangOpts().OpenCLVersion == 120 &&
+ !getOpenCLOptions().cl_clang_storage_class_specifiers &&
+ NewVD->isStaticLocal()) {
Diag(NewVD->getLocation(), diag::err_static_function_scope);
NewVD->setInvalidDecl();
return;
}
+ // OpenCL v1.2 s6.5 - All program scope variables must be declared in the
+ // __constant address space.
+ // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static
+ // variables inside a function can also be declared in the global
+ // address space.
+ if (getLangOpts().OpenCL) {
+ if (NewVD->isFileVarDecl()) {
+ if (!T->isSamplerT() &&
+ !(T.getAddressSpace() == LangAS::opencl_constant ||
+ (T.getAddressSpace() == LangAS::opencl_global &&
+ getLangOpts().OpenCLVersion == 200))) {
+ if (getLangOpts().OpenCLVersion == 200)
+ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
+ << "global or constant";
+ else
+ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
+ << "constant";
+ NewVD->setInvalidDecl();
+ return;
+ }
+ } else {
+ // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static
+ // variables inside a function can also be declared in the global
+ // address space.
+ if (NewVD->isStaticLocal() &&
+ !(T.getAddressSpace() == LangAS::opencl_constant ||
+ (T.getAddressSpace() == LangAS::opencl_global &&
+ getLangOpts().OpenCLVersion == 200))) {
+ if (getLangOpts().OpenCLVersion == 200)
+ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
+ << "global or constant";
+ else
+ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
+ << "constant";
+ NewVD->setInvalidDecl();
+ return;
+ }
+ // OpenCL v1.1 s6.5.2 and s6.5.3 no local or constant variables
+ // in functions.
+ if (T.getAddressSpace() == LangAS::opencl_constant ||
+ T.getAddressSpace() == LangAS::opencl_local) {
+ FunctionDecl *FD = getCurFunctionDecl();
+ if (FD && !FD->hasAttr<OpenCLKernelAttr>()) {
+ if (T.getAddressSpace() == LangAS::opencl_constant)
+ Diag(NewVD->getLocation(), diag::err_opencl_non_kernel_variable)
+ << "constant";
+ else
+ Diag(NewVD->getLocation(), diag::err_opencl_non_kernel_variable)
+ << "local";
+ NewVD->setInvalidDecl();
+ return;
+ }
+ }
+ }
+ }
+
if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
&& !NewVD->hasAttr<BlocksAttr>()) {
if (getLangOpts().getGC() != LangOptions::NonGC)
@@ -6506,9 +6708,6 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
checkForConflictWithNonVisibleExternC(*this, NewVD, Previous))
Previous.setShadowed();
- // Filter out any non-conflicting previous declarations.
- filterNonConflictingPreviousDecls(*this, NewVD, Previous);
-
if (!Previous.empty()) {
MergeVarDecl(NewVD, Previous);
return true;
@@ -6516,50 +6715,45 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
return false;
}
-/// \brief Data used with FindOverriddenMethod
-struct FindOverriddenMethodData {
+namespace {
+struct FindOverriddenMethod {
Sema *S;
CXXMethodDecl *Method;
-};
-/// \brief Member lookup function that determines whether a given C++
-/// method overrides a method in a base class, to be used with
-/// CXXRecordDecl::lookupInBases().
-static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+ /// Member lookup function that determines whether a given C++
+ /// method overrides a method in a base class, to be used with
+ /// CXXRecordDecl::lookupInBases().
+ bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ RecordDecl *BaseRecord =
+ Specifier->getType()->getAs<RecordType>()->getDecl();
- FindOverriddenMethodData *Data
- = reinterpret_cast<FindOverriddenMethodData*>(UserData);
-
- DeclarationName Name = Data->Method->getDeclName();
-
- // FIXME: Do we care about other names here too?
- if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
- // We really want to find the base class destructor here.
- QualType T = Data->S->Context.getTypeDeclType(BaseRecord);
- CanQualType CT = Data->S->Context.getCanonicalType(T);
-
- Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT);
- }
-
- for (Path.Decls = BaseRecord->lookup(Name);
- !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false))
- return true;
+ DeclarationName Name = Method->getDeclName();
+
+ // FIXME: Do we care about other names here too?
+ if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+ // We really want to find the base class destructor here.
+ QualType T = S->Context.getTypeDeclType(BaseRecord);
+ CanQualType CT = S->Context.getCanonicalType(T);
+
+ Name = S->Context.DeclarationNames.getCXXDestructorName(CT);
}
+
+ for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
+ Path.Decls = Path.Decls.slice(1)) {
+ NamedDecl *D = Path.Decls.front();
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->isVirtual() && !S->IsOverload(Method, MD, false))
+ return true;
+ }
+ }
+
+ return false;
}
-
- return false;
-}
+};
+
+enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
+} // end anonymous namespace
-namespace {
- enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
-}
/// \brief Report an error regarding overriding, along with any relevant
/// overriden methods.
///
@@ -6587,13 +6781,13 @@ static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD,
bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
// Look for methods in base classes that this method might override.
CXXBasePaths Paths;
- FindOverriddenMethodData Data;
- Data.Method = MD;
- Data.S = this;
+ FindOverriddenMethod FOM;
+ FOM.Method = MD;
+ FOM.S = this;
bool hasDeletedOverridenMethods = false;
bool hasNonDeletedOverridenMethods = false;
bool AddedAny = false;
- if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
+ if (DC->lookupInBases(FOM, Paths)) {
for (auto *I : Paths.found_decls()) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
@@ -7200,7 +7394,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< DeclSpec::getSpecifierName(TSCS);
if (D.isFirstDeclarationOfMember())
- adjustMemberFunctionCC(R, D.isStaticMember());
+ adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(),
+ D.getIdentifierLoc());
bool isFriend = false;
FunctionTemplateDecl *FunctionTemplate = nullptr;
@@ -7236,6 +7431,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
+ bool isConcept = D.getDeclSpec().isConceptSpecified();
isFriend = D.getDeclSpec().isFriendSpecified();
if (isFriend && !isInline && D.isFunctionDefinition()) {
// C++ [class.friend]p5
@@ -7309,17 +7505,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// For source fidelity, store the other template param lists.
if (TemplateParamLists.size() > 1) {
NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size() - 1,
- TemplateParamLists.data());
+ TemplateParamLists.drop_back(1));
}
} else {
// This is a function template specialization.
isFunctionTemplateSpecialization = true;
// For source fidelity, store all the template param lists.
if (TemplateParamLists.size() > 0)
- NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size(),
- TemplateParamLists.data());
+ NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
if (isFriend) {
@@ -7349,9 +7542,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// this is NOT (an explicit specialization of) a template.
if (TemplateParamLists.size() > 0)
// For source fidelity, store all the template param lists.
- NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size(),
- TemplateParamLists.data());
+ NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
}
if (Invalid) {
@@ -7452,6 +7643,67 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor);
}
+ if (isConcept) {
+ // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+ // applied only to the definition of a function template [...]
+ if (!D.isFunctionDefinition()) {
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag::err_function_concept_not_defined);
+ NewFD->setInvalidDecl();
+ }
+
+ // C++ Concepts TS [dcl.spec.concept]p1: [...] A function concept shall
+ // have no exception-specification and is treated as if it were specified
+ // with noexcept(true) (15.4). [...]
+ if (const FunctionProtoType *FPT = R->getAs<FunctionProtoType>()) {
+ if (FPT->hasExceptionSpec()) {
+ SourceRange Range;
+ if (D.isFunctionDeclarator())
+ Range = D.getFunctionTypeInfo().getExceptionSpecRange();
+ Diag(NewFD->getLocation(), diag::err_function_concept_exception_spec)
+ << FixItHint::CreateRemoval(Range);
+ NewFD->setInvalidDecl();
+ } else {
+ Context.adjustExceptionSpec(NewFD, EST_BasicNoexcept);
+ }
+
+ // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the
+ // following restrictions:
+ // - The declaration's parameter list shall be equivalent to an empty
+ // parameter list.
+ if (FPT->getNumParams() > 0 || FPT->isVariadic())
+ Diag(NewFD->getLocation(), diag::err_function_concept_with_params);
+ }
+
+ // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is
+ // implicity defined to be a constexpr declaration (implicitly inline)
+ NewFD->setImplicitlyInline();
+
+ // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
+ // be declared with the thread_local, inline, friend, or constexpr
+ // specifiers, [...]
+ if (isInline) {
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 1 << 1;
+ NewFD->setInvalidDecl(true);
+ }
+
+ if (isFriend) {
+ Diag(D.getDeclSpec().getFriendSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 1 << 2;
+ NewFD->setInvalidDecl(true);
+ }
+
+ if (isConstexpr) {
+ Diag(D.getDeclSpec().getConstexprSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 1 << 3;
+ NewFD->setInvalidDecl(true);
+ }
+ }
+
// If __module_private__ was specified, mark the function accordingly.
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (isFunctionTemplateSpecialization) {
@@ -7539,13 +7791,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
SE->getString(), 0));
- } else if (!ExtnameUndeclaredIdentifiers.empty() &&
- isDeclTUScopedExternallyVisible(NewFD)) {
+ } else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
- NewFD->addAttr(I->second);
- ExtnameUndeclaredIdentifiers.erase(I);
+ if (isDeclExternC(NewFD)) {
+ NewFD->addAttr(I->second);
+ ExtnameUndeclaredIdentifiers.erase(I);
+ } else
+ Diag(NewFD->getLocation(), diag::warn_redefine_extname_not_applied)
+ << /*Variable*/0 << NewFD;
}
}
@@ -8061,9 +8316,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
bool MergeTypeWithPrevious = !getLangOpts().CPlusPlus &&
!Previous.isShadowed();
- // Filter out any non-conflicting previous declarations.
- filterNonConflictingPreviousDecls(*this, NewFD, Previous);
-
bool Redeclaration = false;
NamedDecl *OldDecl = nullptr;
@@ -8075,7 +8327,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// there's no more work to do here; we'll just add the new
// function to the scope.
if (!AllowOverloadingOfFunction(Previous, Context)) {
- NamedDecl *Candidate = Previous.getFoundDecl();
+ NamedDecl *Candidate = Previous.getRepresentativeDecl();
if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) {
Redeclaration = true;
OldDecl = Candidate;
@@ -8117,7 +8369,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// Check for a previous extern "C" declaration with this name.
if (!Redeclaration &&
checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) {
- filterNonConflictingPreviousDecls(*this, NewFD, Previous);
if (!Previous.empty()) {
// This is an extern "C" declaration with the same name as a previous
// declaration, and thus redeclares that entity...
@@ -8294,7 +8545,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
// The type of this function differs from the type of the builtin,
// so forget about the builtin entirely.
- Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents);
+ Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents);
}
}
@@ -8577,9 +8828,8 @@ namespace {
// Convert FieldDecls to their index number.
llvm::SmallVector<unsigned, 4> UsedFieldIndex;
- for (auto I = Fields.rbegin(), E = Fields.rend(); I != E; ++I) {
- UsedFieldIndex.push_back((*I)->getFieldIndex());
- }
+ for (const FieldDecl *I : llvm::reverse(Fields))
+ UsedFieldIndex.push_back(I->getFieldIndex());
// See if a warning is needed by checking the first difference in index
// numbers. If field being used has index less than the field being
@@ -8832,6 +9082,96 @@ namespace {
}
}
+QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
+ DeclarationName Name, QualType Type,
+ TypeSourceInfo *TSI,
+ SourceRange Range, bool DirectInit,
+ Expr *Init) {
+ bool IsInitCapture = !VDecl;
+ assert((!VDecl || !VDecl->isInitCapture()) &&
+ "init captures are expected to be deduced prior to initialization");
+
+ ArrayRef<Expr *> DeduceInits = Init;
+ if (DirectInit) {
+ if (auto *PL = dyn_cast<ParenListExpr>(Init))
+ DeduceInits = PL->exprs();
+ else if (auto *IL = dyn_cast<InitListExpr>(Init))
+ DeduceInits = IL->inits();
+ }
+
+ // Deduction only works if we have exactly one source expression.
+ if (DeduceInits.empty()) {
+ // It isn't possible to write this directly, but it is possible to
+ // end up in this situation with "auto x(some_pack...);"
+ Diag(Init->getLocStart(), IsInitCapture
+ ? diag::err_init_capture_no_expression
+ : diag::err_auto_var_init_no_expression)
+ << Name << Type << Range;
+ return QualType();
+ }
+
+ if (DeduceInits.size() > 1) {
+ Diag(DeduceInits[1]->getLocStart(),
+ IsInitCapture ? diag::err_init_capture_multiple_expressions
+ : diag::err_auto_var_init_multiple_expressions)
+ << Name << Type << Range;
+ return QualType();
+ }
+
+ Expr *DeduceInit = DeduceInits[0];
+ if (DirectInit && isa<InitListExpr>(DeduceInit)) {
+ Diag(Init->getLocStart(), IsInitCapture
+ ? diag::err_init_capture_paren_braces
+ : diag::err_auto_var_init_paren_braces)
+ << isa<InitListExpr>(Init) << Name << Type << Range;
+ return QualType();
+ }
+
+ // Expressions default to 'id' when we're in a debugger.
+ bool DefaultedAnyToId = false;
+ if (getLangOpts().DebuggerCastResultToId &&
+ Init->getType() == Context.UnknownAnyTy && !IsInitCapture) {
+ ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
+ if (Result.isInvalid()) {
+ return QualType();
+ }
+ Init = Result.get();
+ DefaultedAnyToId = true;
+ }
+
+ QualType DeducedType;
+ if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) {
+ if (!IsInitCapture)
+ DiagnoseAutoDeductionFailure(VDecl, DeduceInit);
+ else if (isa<InitListExpr>(Init))
+ Diag(Range.getBegin(),
+ diag::err_init_capture_deduction_failure_from_init_list)
+ << Name
+ << (DeduceInit->getType().isNull() ? TSI->getType()
+ : DeduceInit->getType())
+ << DeduceInit->getSourceRange();
+ else
+ Diag(Range.getBegin(), diag::err_init_capture_deduction_failure)
+ << Name << TSI->getType()
+ << (DeduceInit->getType().isNull() ? TSI->getType()
+ : DeduceInit->getType())
+ << DeduceInit->getSourceRange();
+ }
+
+ // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using
+ // 'id' instead of a specific object type prevents most of our usual
+ // checks.
+ // We only want to warn outside of template instantiations, though:
+ // inside a template, the 'id' could have come from a parameter.
+ if (ActiveTemplateInstantiations.empty() && !DefaultedAnyToId &&
+ !IsInitCapture && !DeducedType.isNull() && DeducedType->isObjCIdType()) {
+ SourceLocation Loc = TSI->getTypeLoc().getBeginLoc();
+ Diag(Loc, diag::warn_auto_var_is_id) << Name << Range;
+ }
+
+ return DeducedType;
+}
+
/// AddInitializerToDecl - Adds the initializer Init to the
/// declaration dcl. If DirectInit is true, this is C++ direct
/// initialization rather than copy initialization.
@@ -8859,79 +9199,27 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
RealDecl->setInvalidDecl();
return;
}
- ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) {
// Attempt typo correction early so that the type of the init expression can
- // be deduced based on the chosen correction:if the original init contains a
+ // be deduced based on the chosen correction if the original init contains a
// TypoExpr.
ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl);
if (!Res.isUsable()) {
RealDecl->setInvalidDecl();
return;
}
+ Init = Res.get();
- if (Res.get() != Init) {
- Init = Res.get();
- if (CXXDirectInit)
- CXXDirectInit = dyn_cast<ParenListExpr>(Init);
- }
-
- Expr *DeduceInit = Init;
- // Initializer could be a C++ direct-initializer. Deduction only works if it
- // contains exactly one expression.
- if (CXXDirectInit) {
- if (CXXDirectInit->getNumExprs() == 0) {
- // It isn't possible to write this directly, but it is possible to
- // end up in this situation with "auto x(some_pack...);"
- Diag(CXXDirectInit->getLocStart(),
- VDecl->isInitCapture() ? diag::err_init_capture_no_expression
- : diag::err_auto_var_init_no_expression)
- << VDecl->getDeclName() << VDecl->getType()
- << VDecl->getSourceRange();
- RealDecl->setInvalidDecl();
- return;
- } else if (CXXDirectInit->getNumExprs() > 1) {
- Diag(CXXDirectInit->getExpr(1)->getLocStart(),
- VDecl->isInitCapture()
- ? diag::err_init_capture_multiple_expressions
- : diag::err_auto_var_init_multiple_expressions)
- << VDecl->getDeclName() << VDecl->getType()
- << VDecl->getSourceRange();
- RealDecl->setInvalidDecl();
- return;
- } else {
- DeduceInit = CXXDirectInit->getExpr(0);
- if (isa<InitListExpr>(DeduceInit))
- Diag(CXXDirectInit->getLocStart(),
- diag::err_auto_var_init_paren_braces)
- << VDecl->getDeclName() << VDecl->getType()
- << VDecl->getSourceRange();
- }
- }
-
- // Expressions default to 'id' when we're in a debugger.
- bool DefaultedToAuto = false;
- if (getLangOpts().DebuggerCastResultToId &&
- Init->getType() == Context.UnknownAnyTy) {
- ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
- if (Result.isInvalid()) {
- VDecl->setInvalidDecl();
- return;
- }
- Init = Result.get();
- DefaultedToAuto = true;
- }
-
- QualType DeducedType;
- if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
- DAR_Failed)
- DiagnoseAutoDeductionFailure(VDecl, DeduceInit);
+ QualType DeducedType = deduceVarTypeFromInitializer(
+ VDecl, VDecl->getDeclName(), VDecl->getType(),
+ VDecl->getTypeSourceInfo(), VDecl->getSourceRange(), DirectInit, Init);
if (DeducedType.isNull()) {
RealDecl->setInvalidDecl();
return;
}
+
VDecl->setType(DeducedType);
assert(VDecl->isLinkageValid());
@@ -8939,38 +9227,18 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
VDecl->setInvalidDecl();
- // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using
- // 'id' instead of a specific object type prevents most of our usual checks.
- // We only want to warn outside of template instantiations, though:
- // inside a template, the 'id' could have come from a parameter.
- if (ActiveTemplateInstantiations.empty() && !DefaultedToAuto &&
- DeducedType->isObjCIdType()) {
- SourceLocation Loc =
- VDecl->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
- Diag(Loc, diag::warn_auto_var_is_id)
- << VDecl->getDeclName() << DeduceInit->getSourceRange();
- }
-
// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
if (VarDecl *Old = VDecl->getPreviousDecl()) {
// We never need to merge the type, because we cannot form an incomplete
// array of auto, nor deduce such a type.
- MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/false);
+ MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/ false);
}
// Check the deduced type is valid for a variable declaration.
CheckVariableDeclarationType(VDecl);
if (VDecl->isInvalidDecl())
return;
-
- // If all looks well, warn if this is a case that will change meaning when
- // we implement N3922.
- if (DirectInit && !CXXDirectInit && isa<InitListExpr>(Init)) {
- Diag(Init->getLocStart(),
- diag::warn_auto_var_direct_list_init)
- << FixItHint::CreateInsertion(Init->getLocStart(), "=");
- }
}
// dllimport cannot be used on variable definitions.
@@ -9059,7 +9327,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// OpenCL 1.1 6.5.2: "Variables allocated in the __local address space inside
// a kernel function cannot be initialized."
- if (VDecl->getStorageClass() == SC_OpenCLWorkGroupLocal) {
+ if (VDecl->getType().getAddressSpace() == LangAS::opencl_local) {
Diag(VDecl->getLocation(), diag::err_local_cant_init);
VDecl->setInvalidDecl();
return;
@@ -9082,17 +9350,18 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
// Perform the initialization.
+ ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
if (!VDecl->isInvalidDecl()) {
InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
- InitializationKind Kind
- = DirectInit ?
- CXXDirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(),
- Init->getLocStart(),
- Init->getLocEnd())
- : InitializationKind::CreateDirectList(
- VDecl->getLocation())
- : InitializationKind::CreateCopy(VDecl->getLocation(),
- Init->getLocStart());
+ InitializationKind Kind =
+ DirectInit
+ ? CXXDirectInit
+ ? InitializationKind::CreateDirect(VDecl->getLocation(),
+ Init->getLocStart(),
+ Init->getLocEnd())
+ : InitializationKind::CreateDirectList(VDecl->getLocation())
+ : InitializationKind::CreateCopy(VDecl->getLocation(),
+ Init->getLocStart());
MultiExprArg Args = Init;
if (CXXDirectInit)
@@ -9156,7 +9425,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
Init->getLocStart()))
- getCurFunction()->markSafeWeakUse(Init);
+ getCurFunction()->markSafeWeakUse(Init);
}
// The initialization is usually a full-expression.
@@ -9409,6 +9678,15 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
return;
}
+ // C++ Concepts TS [dcl.spec.concept]p1: [...] A variable template
+ // definition having the concept specifier is called a variable concept. A
+ // concept definition refers to [...] a variable concept and its initializer.
+ if (Var->isConcept()) {
+ Diag(Var->getLocation(), diag::err_var_concept_not_initialized);
+ Var->setInvalidDecl();
+ return;
+ }
+
// OpenCL v1.1 s6.5.3: variables declared in the constant address space must
// be initialized.
if (!Var->isInvalidDecl() &&
@@ -9621,8 +9899,6 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
case SC_Register:
Error = 4;
break;
- case SC_OpenCLWorkGroupLocal:
- llvm_unreachable("Unexpected storage class");
}
if (Error != -1) {
Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
@@ -9665,9 +9941,9 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isInvalidDecl()) return;
- // In ARC, don't allow jumps past the implicit initialization of a
+ // In Objective-C, don't allow jumps past the implicit initialization of a
// local retaining variable.
- if (getLangOpts().ObjCAutoRefCount &&
+ if (getLangOpts().ObjC1 &&
var->hasLocalStorage()) {
switch (var->getType().getObjCLifetime()) {
case Qualifiers::OCL_None:
@@ -9913,9 +10189,17 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
// dllimport/dllexport variables cannot be thread local, their TLS index
// isn't exported with the variable.
if (DLLAttr && VD->getTLSKind()) {
- Diag(VD->getLocation(), diag::err_attribute_dll_thread_local) << VD
- << DLLAttr;
- VD->setInvalidDecl();
+ auto *F = dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod());
+ if (F && getDLLAttr(F)) {
+ assert(VD->isStaticLocal());
+ // But if this is a static local in a dlimport/dllexport function, the
+ // function will never be inlined, which means the var would never be
+ // imported, so having it marked import/export is safe.
+ } else {
+ Diag(VD->getLocation(), diag::err_attribute_dll_thread_local) << VD
+ << DLLAttr;
+ VD->setInvalidDecl();
+ }
}
if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
@@ -9988,8 +10272,9 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
handleTagNumbering(Tag, S);
- if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl())
- Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup);
+ if (FirstDeclaratorInGroup && !Tag->hasNameForLinkage() &&
+ getLangOpts().CPlusPlus)
+ Context.addDeclaratorForUnnamedTagDecl(Tag, FirstDeclaratorInGroup);
}
}
@@ -10028,7 +10313,7 @@ Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group,
} else if (DeducedCanon != UCanon) {
Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
diag::err_auto_different_deductions)
- << (AT->isDecltypeAuto() ? 1 : 0)
+ << (unsigned)AT->getKeyword()
<< Deduced << DeducedDecl->getDeclName()
<< U << D->getDeclName()
<< DeducedDecl->getInit()->getSourceRange()
@@ -10118,6 +10403,8 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (DS.isConstexprSpecified())
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 0;
+ if (DS.isConceptSpecified())
+ Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind);
DiagnoseFunctionSpecifiers(DS);
@@ -10370,14 +10657,17 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
}
}
-Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
+Decl *
+Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ SkipBodyInfo *SkipBody) {
assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
assert(D.isFunctionDeclarator() && "Not a function declarator!");
Scope *ParentScope = FnBodyScope->getParent();
D.setFunctionDefinitionKind(FDK_Definition);
- Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg());
- return ActOnStartOfFunctionDef(FnBodyScope, DP);
+ Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists);
+ return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
}
void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) {
@@ -10441,7 +10731,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
void
Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
- const FunctionDecl *EffectiveDefinition) {
+ const FunctionDecl *EffectiveDefinition,
+ SkipBodyInfo *SkipBody) {
// Don't complain if we're in GNU89 mode and the previous definition
// was an extern inline function.
const FunctionDecl *Definition = EffectiveDefinition;
@@ -10453,17 +10744,20 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
return;
// If we don't have a visible definition of the function, and it's inline or
- // a template, it's OK to form another definition of it.
- //
- // FIXME: Should we skip the body of the function and use the old definition
- // in this case? That may be necessary for functions that return local types
- // through a deduced return type, or instantiate templates with local types.
- if (!hasVisibleDefinition(Definition) &&
+ // a template, skip the new definition.
+ if (SkipBody && !hasVisibleDefinition(Definition) &&
(Definition->getFormalLinkage() == InternalLinkage ||
Definition->isInlined() ||
Definition->getDescribedFunctionTemplate() ||
- Definition->getNumTemplateParameterLists()))
+ Definition->getNumTemplateParameterLists())) {
+ SkipBody->ShouldSkip = true;
+ if (auto *TD = Definition->getDescribedFunctionTemplate())
+ makeMergedDefinitionVisible(TD, FD->getLocation());
+ else
+ makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition),
+ FD->getLocation());
return;
+ }
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
Definition->getStorageClass() == SC_Extern)
@@ -10524,7 +10818,8 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
}
}
-Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
+ SkipBodyInfo *SkipBody) {
// Clear the last template instantiation error context.
LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
@@ -10536,6 +10831,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
FD = FunTmpl->getTemplatedDecl();
else
FD = cast<FunctionDecl>(D);
+
+ // See if this is a redefinition.
+ if (!FD->isLateTemplateParsed()) {
+ CheckForFunctionRedefinition(FD, nullptr, SkipBody);
+
+ // If we're skipping the body, we're done. Don't enter the scope.
+ if (SkipBody && SkipBody->ShouldSkip)
+ return D;
+ }
+
// If we are instantiating a generic lambda call operator, push
// a LambdaScopeInfo onto the function stack. But use the information
// that's already been calculated (ActOnLambdaExpr) to prime the current
@@ -10555,10 +10860,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// Enter a new function scope
PushFunctionScope();
- // See if this is a redefinition.
- if (!FD->isLateTemplateParsed())
- CheckForFunctionRedefinition(FD);
-
// Builtin functions cannot be defined.
if (unsigned BuiltinID = FD->getBuiltinID()) {
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
@@ -10734,6 +11035,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
+ if (getLangOpts().Coroutines && !getCurFunction()->CoroutineStmts.empty())
+ CheckCompletedCoroutineBody(FD, Body);
+
if (FD) {
FD->setBody(Body);
@@ -11073,7 +11377,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc,
EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
@@ -11159,6 +11463,18 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation()));
if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->hasAttr<ConstAttr>())
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads &&
+ Context.BuiltinInfo.isTSBuiltin(BuiltinID) &&
+ !FD->hasAttr<CUDADeviceAttr>() && !FD->hasAttr<CUDAHostAttr>()) {
+ // Assign appropriate attribute depending on CUDA compilation
+ // mode and the target builtin belongs to. E.g. during host
+ // compilation, aux builtins are __device__, the rest are __host__.
+ if (getLangOpts().CUDAIsDevice !=
+ Context.BuiltinInfo.isAuxBuiltinID(BuiltinID))
+ FD->addAttr(CUDADeviceAttr::CreateImplicit(Context, FD->getLocation()));
+ else
+ FD->addAttr(CUDAHostAttr::CreateImplicit(Context, FD->getLocation()));
+ }
}
IdentifierInfo *Name = FD->getIdentifier();
@@ -11269,9 +11585,9 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
/// Check whether this is a valid redeclaration of a previous enumeration.
/// \return true if the redeclaration was invalid.
-bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
- QualType EnumUnderlyingTy,
- const EnumDecl *Prev) {
+bool Sema::CheckEnumRedeclaration(
+ SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy,
+ bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) {
bool IsFixed = !EnumUnderlyingTy.isNull();
if (IsScoped != Prev->isScoped()) {
@@ -11293,6 +11609,10 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
<< Prev->getIntegerTypeRange();
return true;
}
+ } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) {
+ ;
+ } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) {
+ ;
} else if (IsFixed != Prev->isFixed()) {
Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
<< Prev->isFixed();
@@ -11459,7 +11779,6 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S,
std::reverse(Namespaces.begin(), Namespaces.end());
for (auto *II : Namespaces)
OS << II->getName() << "::";
- OS.flush();
return FixItHint::CreateInsertion(NameLoc, Insertion);
}
@@ -11563,6 +11882,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// this early, because it's needed to detect if this is an incompatible
// redeclaration.
llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
+ bool EnumUnderlyingIsImplicit = false;
if (Kind == TTK_Enum) {
if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
@@ -11584,9 +11904,13 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
UPPC_FixedUnderlyingType))
EnumUnderlying = Context.IntTy.getTypePtr();
- } else if (getLangOpts().MSVCCompat)
- // Microsoft enums are always of int type.
- EnumUnderlying = Context.IntTy.getTypePtr();
+ } else if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (getLangOpts().MSVCCompat || TUK == TUK_Definition) {
+ // Microsoft enums are always of int type.
+ EnumUnderlying = Context.IntTy.getTypePtr();
+ EnumUnderlyingIsImplicit = true;
+ }
+ }
}
DeclContext *SearchDC = CurContext;
@@ -11816,9 +12140,16 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// In C++, we need to do a redeclaration lookup to properly
// diagnose some problems.
+ // FIXME: redeclaration lookup is also used (with and without C++) to find a
+ // hidden declaration so that we don't get ambiguity errors when using a
+ // type declared by an elaborated-type-specifier. In C that is not correct
+ // and we should instead merge compatible types found by lookup.
if (getLangOpts().CPlusPlus) {
Previous.setRedeclarationKind(ForRedeclaration);
LookupQualifiedName(Previous, SearchDC);
+ } else {
+ Previous.setRedeclarationKind(ForRedeclaration);
+ LookupName(Previous, S);
}
}
@@ -11932,7 +12263,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// returning the previous declaration, unless this is a definition,
// in which case we want the caller to bail out.
if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
- ScopedEnum, EnumUnderlyingTy, PrevEnum))
+ ScopedEnum, EnumUnderlyingTy,
+ EnumUnderlyingIsImplicit, PrevEnum))
return TUK == TUK_Declaration ? PrevTagDecl : nullptr;
}
@@ -12203,9 +12535,7 @@ CreateNewDecl:
New->setQualifierInfo(SS.getWithLocInContext(Context));
if (TemplateParameterLists.size() > 0) {
- New->setTemplateParameterListsInfo(Context,
- TemplateParameterLists.size(),
- TemplateParameterLists.data());
+ New->setTemplateParameterListsInfo(Context, TemplateParameterLists);
}
}
else
@@ -12504,26 +12834,41 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
}
if (!FieldTy->isDependentType()) {
- uint64_t TypeSize = Context.getTypeSize(FieldTy);
- if (Value.getZExtValue() > TypeSize) {
- if (!getLangOpts().CPlusPlus || IsMsStruct ||
- Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (FieldName)
- return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
- << FieldName << (unsigned)Value.getZExtValue()
- << (unsigned)TypeSize;
-
- return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size)
- << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
- }
-
+ uint64_t TypeStorageSize = Context.getTypeSize(FieldTy);
+ uint64_t TypeWidth = Context.getIntWidth(FieldTy);
+ bool BitfieldIsOverwide = Value.ugt(TypeWidth);
+
+ // Over-wide bitfields are an error in C or when using the MSVC bitfield
+ // ABI.
+ bool CStdConstraintViolation =
+ BitfieldIsOverwide && !getLangOpts().CPlusPlus;
+ bool MSBitfieldViolation =
+ Value.ugt(TypeStorageSize) &&
+ (IsMsStruct || Context.getTargetInfo().getCXXABI().isMicrosoft());
+ if (CStdConstraintViolation || MSBitfieldViolation) {
+ unsigned DiagWidth =
+ CStdConstraintViolation ? TypeWidth : TypeStorageSize;
+ if (FieldName)
+ return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width)
+ << FieldName << (unsigned)Value.getZExtValue()
+ << !CStdConstraintViolation << DiagWidth;
+
+ return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width)
+ << (unsigned)Value.getZExtValue() << !CStdConstraintViolation
+ << DiagWidth;
+ }
+
+ // Warn on types where the user might conceivably expect to get all
+ // specified bits as value bits: that's all integral types other than
+ // 'bool'.
+ if (BitfieldIsOverwide && !FieldTy->isBooleanType()) {
if (FieldName)
- Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_size)
- << FieldName << (unsigned)Value.getZExtValue()
- << (unsigned)TypeSize;
+ Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
+ << FieldName << (unsigned)Value.getZExtValue()
+ << (unsigned)TypeWidth;
else
- Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size)
- << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
+ Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width)
+ << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth;
}
}
@@ -12866,9 +13211,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
SourceLocation Loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(Loc)) {
if (!FD->hasAttr<UnavailableAttr>())
- FD->addAttr(UnavailableAttr::CreateImplicit(Context,
- "this system field has retaining ownership",
- Loc));
+ FD->addAttr(UnavailableAttr::CreateImplicit(Context, "",
+ UnavailableAttr::IR_ARCFieldWithOwnership, Loc));
return false;
}
}
@@ -12876,7 +13220,7 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member :
diag::err_illegal_union_or_anon_struct_member)
- << (int)FD->getParent()->isUnion() << FD->getDeclName() << member;
+ << FD->getParent()->isUnion() << FD->getDeclName() << member;
DiagnoseNontrivial(RDecl, member);
return !getLangOpts().CPlusPlus11;
}
@@ -13237,9 +13581,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
SourceLocation loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(loc)) {
if (!FD->hasAttr<UnavailableAttr>()) {
- FD->addAttr(UnavailableAttr::CreateImplicit(Context,
- "this system field has retaining ownership",
- loc));
+ FD->addAttr(UnavailableAttr::CreateImplicit(Context, "",
+ UnavailableAttr::IR_ARCFieldWithOwnership, loc));
}
} else {
Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
@@ -13687,10 +14030,12 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName,
ForRedeclaration);
auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl);
+ if (!PrevECD)
+ return SkipBodyInfo();
+
+ EnumDecl *PrevED = cast<EnumDecl>(PrevECD->getDeclContext());
NamedDecl *Hidden;
- if (PrevECD &&
- !hasVisibleDefinition(cast<NamedDecl>(PrevECD->getDeclContext()),
- &Hidden)) {
+ if (!PrevED->getDeclName() && !hasVisibleDefinition(PrevED, &Hidden)) {
SkipBodyInfo Skip;
Skip.Previous = Hidden;
return Skip;
@@ -13722,12 +14067,27 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
PrevDecl = nullptr;
}
+ // C++ [class.mem]p15:
+ // If T is the name of a class, then each of the following shall have a name
+ // different from T:
+ // - every enumerator of every member of class T that is an unscoped
+ // enumerated type
+ if (!TheEnumDecl->isScoped())
+ DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(),
+ DeclarationNameInfo(Id, IdLoc));
+
+ EnumConstantDecl *New =
+ CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
+ if (!New)
+ return nullptr;
+
if (PrevDecl) {
// When in C++, we may get a TagDecl with the same name; in this case the
// enum constant will 'hide' the tag.
assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
"Received TagDecl when not in C++!");
- if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
+ if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S) &&
+ shouldLinkPossiblyHiddenDecl(PrevDecl, New)) {
if (isa<EnumConstantDecl>(PrevDecl))
Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
else
@@ -13737,26 +14097,12 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
}
}
- // C++ [class.mem]p15:
- // If T is the name of a class, then each of the following shall have a name
- // different from T:
- // - every enumerator of every member of class T that is an unscoped
- // enumerated type
- if (!TheEnumDecl->isScoped())
- DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(),
- DeclarationNameInfo(Id, IdLoc));
-
- EnumConstantDecl *New =
- CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
+ // Process attributes.
+ if (Attr) ProcessDeclAttributeList(S, New, Attr);
- if (New) {
- // Process attributes.
- if (Attr) ProcessDeclAttributeList(S, New, Attr);
-
- // Register this decl in the current scope stack.
- New->setAccess(TheEnumDecl->getAccess());
- PushOnScopeChains(New, S);
- }
+ // Register this decl in the current scope stack.
+ New->setAccess(TheEnumDecl->getAccess());
+ PushOnScopeChains(New, S);
ActOnDocumentableDecl(New);
@@ -13803,6 +14149,7 @@ static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) {
return false;
}
+namespace {
struct DupKey {
int64_t val;
bool isTombstoneOrEmptyKey;
@@ -13826,6 +14173,7 @@ struct DenseMapInfoDupKey {
LHS.val == RHS.val;
}
};
+} // end anonymous namespace
// Emits a warning when an element is implicitly set a value that
// a previous element has already been set to.
@@ -13937,17 +14285,22 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
}
}
-bool
-Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
- bool AllowMask) const {
- FlagEnumAttr *FEAttr = ED->getAttr<FlagEnumAttr>();
- assert(FEAttr && "looking for value in non-flag enum");
+bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
+ bool AllowMask) const {
+ assert(ED->hasAttr<FlagEnumAttr>() && "looking for value in non-flag enum");
+ assert(ED->isCompleteDefinition() && "expected enum definition");
- llvm::APInt FlagMask = ~FEAttr->getFlagBits();
- unsigned Width = FlagMask.getBitWidth();
+ auto R = FlagBitsCache.insert(std::make_pair(ED, llvm::APInt()));
+ llvm::APInt &FlagBits = R.first->second;
- // We will try a zero-extended value for the regular check first.
- llvm::APInt ExtVal = Val.zextOrSelf(Width);
+ if (R.second) {
+ for (auto *E : ED->enumerators()) {
+ const auto &EVal = E->getInitVal();
+ // Only single-bit enumerators introduce new flag values.
+ if (EVal.isPowerOf2())
+ FlagBits = FlagBits.zextOrSelf(EVal.getBitWidth()) | EVal;
+ }
+ }
// A value is in a flag enum if either its bits are a subset of the enum's
// flag bits (the first condition) or we are allowing masks and the same is
@@ -13957,27 +14310,8 @@ Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
// While it's true that any value could be used as a mask, the assumption is
// that a mask will have all of the insignificant bits set. Anything else is
// likely a logic error.
- if (!(FlagMask & ExtVal))
- return true;
-
- if (AllowMask) {
- // Try a one-extended value instead. This can happen if the enum is wider
- // than the constant used, in C with extensions to allow for wider enums.
- // The mask will still have the correct behaviour, so we give the user the
- // benefit of the doubt.
- //
- // FIXME: This heuristic can cause weird results if the enum was extended
- // to a larger type and is signed, because then bit-masks of smaller types
- // that get extended will fall out of range (e.g. ~0x1u). We currently don't
- // detect that case and will get a false positive for it. In most cases,
- // though, it can be fixed by making it a signed type (e.g. ~0x1), so it may
- // be fine just to accept this as a warning.
- ExtVal |= llvm::APInt::getHighBitsSet(Width, Width - Val.getBitWidth());
- if (!(FlagMask & ~ExtVal))
- return true;
- }
-
- return false;
+ llvm::APInt FlagMask = ~FlagBits.zextOrTrunc(Val.getBitWidth());
+ return !(FlagMask & Val) || (AllowMask && !(FlagMask & ~Val));
}
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
@@ -14131,13 +14465,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
}
}
- FlagEnumAttr *FEAttr = Enum->getAttr<FlagEnumAttr>();
- if (FEAttr)
- FEAttr->getFlagBits() = llvm::APInt(BestWidth, 0);
-
// Loop over all of the enumerator constants, changing their types to match
- // the type of the enum if needed. If we have a flag type, we also prepare the
- // FlagBits cache.
+ // the type of the enum if needed.
for (auto *D : Elements) {
auto *ECD = cast_or_null<EnumConstantDecl>(D);
if (!ECD) continue; // Already issued a diagnostic.
@@ -14169,7 +14498,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// enum-specifier, each enumerator has the type of its
// enumeration.
ECD->setType(EnumType);
- goto flagbits;
+ continue;
} else {
NewTy = BestType;
NewWidth = BestWidth;
@@ -14196,37 +14525,26 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
ECD->setType(EnumType);
else
ECD->setType(NewTy);
-
-flagbits:
- // Check to see if we have a constant with exactly one bit set. Note that x
- // & (x - 1) will be nonzero if and only if x has more than one bit set.
- if (FEAttr) {
- llvm::APInt ExtVal = InitVal.zextOrSelf(BestWidth);
- if (ExtVal != 0 && !(ExtVal & (ExtVal - 1))) {
- FEAttr->getFlagBits() |= ExtVal;
- }
- }
}
- if (FEAttr) {
+ Enum->completeDefinition(BestType, BestPromotionType,
+ NumPositiveBits, NumNegativeBits);
+
+ CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
+
+ if (Enum->hasAttr<FlagEnumAttr>()) {
for (Decl *D : Elements) {
EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(D);
if (!ECD) continue; // Already issued a diagnostic.
llvm::APSInt InitVal = ECD->getInitVal();
- if (InitVal != 0 && !IsValueInFlagEnum(Enum, InitVal, true))
+ if (InitVal != 0 && !InitVal.isPowerOf2() &&
+ !IsValueInFlagEnum(Enum, InitVal, true))
Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range)
<< ECD << Enum;
}
}
-
-
- Enum->completeDefinition(BestType, BestPromotionType,
- NumPositiveBits, NumNegativeBits);
-
- CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
-
// Now that the enum type is defined, ensure it's not been underaligned.
if (Enum->hasAttrs())
CheckAlignasUnderalignment(Enum);
@@ -14245,17 +14563,15 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
}
static void checkModuleImportContext(Sema &S, Module *M,
- SourceLocation ImportLoc,
- DeclContext *DC) {
+ SourceLocation ImportLoc, DeclContext *DC,
+ bool FromInclude = false) {
+ SourceLocation ExternCLoc;
+
if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) {
switch (LSD->getLanguage()) {
case LinkageSpecDecl::lang_c:
- if (!M->IsExternC) {
- S.Diag(ImportLoc, diag::err_module_import_in_extern_c)
- << M->getFullModuleName();
- S.Diag(LSD->getLocStart(), diag::note_module_import_in_extern_c);
- return;
- }
+ if (ExternCLoc.isInvalid())
+ ExternCLoc = LSD->getLocStart();
break;
case LinkageSpecDecl::lang_cxx:
break;
@@ -14265,15 +14581,25 @@ static void checkModuleImportContext(Sema &S, Module *M,
while (isa<LinkageSpecDecl>(DC))
DC = DC->getParent();
+
if (!isa<TranslationUnitDecl>(DC)) {
- S.Diag(ImportLoc, diag::err_module_import_not_at_top_level)
- << M->getFullModuleName() << DC;
+ S.Diag(ImportLoc, (FromInclude && S.isModuleVisible(M))
+ ? diag::ext_module_import_not_at_top_level_noop
+ : diag::err_module_import_not_at_top_level_fatal)
+ << M->getFullModuleName() << DC;
S.Diag(cast<Decl>(DC)->getLocStart(),
- diag::note_module_import_not_at_top_level)
- << DC;
+ diag::note_module_import_not_at_top_level) << DC;
+ } else if (!M->IsExternC && ExternCLoc.isValid()) {
+ S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)
+ << M->getFullModuleName();
+ S.Diag(ExternCLoc, diag::note_module_import_in_extern_c);
}
}
+void Sema::diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc) {
+ return checkModuleImportContext(*this, M, ImportLoc, CurContext);
+}
+
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
@@ -14318,7 +14644,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
}
void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
- checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+ checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);
// Determine whether we're in the #include buffer for a module. The #includes
// in that buffer do not qualify as module imports; they're just an
@@ -14394,12 +14720,14 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
// 1) declares a function or a variable
// 2) has external linkage
// already exists, add a label attribute to it.
- if (PrevDecl &&
- (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)) &&
- PrevDecl->hasExternalFormalLinkage())
- PrevDecl->addAttr(Attr);
+ if (PrevDecl && (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl))) {
+ if (isDeclExternC(PrevDecl))
+ PrevDecl->addAttr(Attr);
+ else
+ Diag(PrevDecl->getLocation(), diag::warn_redefine_extname_not_applied)
+ << /*Variable*/(isa<FunctionDecl>(PrevDecl) ? 0 : 1) << PrevDecl;
// Otherwise, add a label atttibute to ExtnameUndeclaredIdentifiers.
- else
+ } else
(void)ExtnameUndeclaredIdentifiers.insert(std::make_pair(Name, Attr));
}
@@ -14426,7 +14754,7 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
LookupOrdinaryName);
WeakInfo W = WeakInfo(Name, NameLoc);
- if (PrevDecl) {
+ if (PrevDecl && (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl))) {
if (!PrevDecl->hasAttr<AliasAttr>())
if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
DeclApplyPragmaWeak(TUScope, ND, W);
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 191dbd05c9bd..5a0f0f84af7e 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -244,11 +244,12 @@ static bool checkUInt32Argument(Sema &S, const AttributeList &Attr,
/// \brief Diagnose mutually exclusive attributes when present on a given
/// declaration. Returns true if diagnosed.
template <typename AttrTy>
-static bool checkAttrMutualExclusion(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range,
+ IdentifierInfo *Ident) {
if (AttrTy *A = D->getAttr<AttrTy>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << Attr.getName() << A;
+ S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) << Ident
+ << A;
+ S.Diag(A->getLocation(), diag::note_conflicting_attribute);
return true;
}
return false;
@@ -315,7 +316,7 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
Diag(Loc->Loc, diag::err_attribute_argument_type)
<< Attr.getName() << AANT_ArgumentString
<< FixItHint::CreateInsertion(Loc->Loc, "\"")
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\"");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\"");
Str = Loc->Ident->getName();
if (ArgLocation)
*ArgLocation = Loc->Loc;
@@ -432,11 +433,10 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
// Else check if any base classes have a capability.
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
CXXBasePaths BPaths(false, false);
- if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &P,
- void *) {
- return BS->getType()->getAs<RecordType>()
- ->getDecl()->hasAttr<CapabilityAttr>();
- }, nullptr, BPaths))
+ if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) {
+ const auto *Type = BS->getType()->getAs<RecordType>();
+ return Type->getDecl()->hasAttr<CapabilityAttr>();
+ }, BPaths))
return true;
}
return false;
@@ -629,13 +629,10 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
// Check that this attribute only applies to lockable types.
QualType QT = cast<ValueDecl>(D)->getType();
- if (!QT->isDependentType()) {
- const RecordType *RT = getRecordType(QT);
- if (!RT || !RT->getDecl()->hasAttr<CapabilityAttr>()) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
- << Attr.getName();
- return false;
- }
+ if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
+ S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
+ << Attr.getName();
+ return false;
}
// Check that all arguments are lockable objects.
@@ -812,6 +809,43 @@ static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
+static void handlePassObjectSizeAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (D->hasAttr<PassObjectSizeAttr>()) {
+ S.Diag(D->getLocStart(), diag::err_attribute_only_once_per_parameter)
+ << Attr.getName();
+ return;
+ }
+
+ Expr *E = Attr.getArgAsExpr(0);
+ uint32_t Type;
+ if (!checkUInt32Argument(S, Attr, E, Type, /*Idx=*/1))
+ return;
+
+ // pass_object_size's argument is passed in as the second argument of
+ // __builtin_object_size. So, it has the same constraints as that second
+ // argument; namely, it must be in the range [0, 3].
+ if (Type > 3) {
+ S.Diag(E->getLocStart(), diag::err_attribute_argument_outof_range)
+ << Attr.getName() << 0 << 3 << E->getSourceRange();
+ return;
+ }
+
+ // pass_object_size is only supported on constant pointer parameters; as a
+ // kindness to users, we allow the parameter to be non-const for declarations.
+ // At this point, we have no clue if `D` belongs to a function declaration or
+ // definition, so we defer the constness check until later.
+ if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) {
+ S.Diag(D->getLocStart(), diag::err_attribute_pointers_only)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ PassObjectSizeAttr(Attr.getRange(), S.Context, (int)Type,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
ConsumableAttr::ConsumedState DefaultState;
@@ -1039,17 +1073,14 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
- // If the alignment is less than or equal to 8 bits, the packed attribute
- // has no effect.
+ // Report warning about changed offset in the newer compiler versions.
if (!FD->getType()->isDependentType() &&
- !FD->getType()->isIncompleteType() &&
+ !FD->getType()->isIncompleteType() && FD->isBitField() &&
S.Context.getTypeAlign(FD->getType()) <= 8)
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
- << Attr.getName() << FD->getType();
- else
- FD->addAttr(::new (S.Context)
- PackedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield);
+
+ FD->addAttr(::new (S.Context) PackedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
@@ -1165,10 +1196,12 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
SourceRange TypeRange,
bool isReturnValue = false) {
if (!S.isValidPointerAttrType(T)) {
- S.Diag(Attr.getLoc(), isReturnValue
- ? diag::warn_attribute_return_pointers_only
- : diag::warn_attribute_pointers_only)
- << Attr.getName() << AttrParmRange << TypeRange;
+ if (isReturnValue)
+ S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
+ << Attr.getName() << AttrParmRange << TypeRange;
+ else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only)
+ << Attr.getName() << AttrParmRange << TypeRange << 0;
return false;
}
return true;
@@ -1312,6 +1345,17 @@ void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
AssumeAlignedAttr(AttrRange, Context, E, OE, SpellingListIndex));
}
+/// Normalize the attribute, __foo__ becomes foo.
+/// Returns true if normalization was applied.
+static bool normalizeName(StringRef &AttrName) {
+ if (AttrName.size() > 4 && AttrName.startswith("__") &&
+ AttrName.endswith("__")) {
+ AttrName = AttrName.drop_front(2).drop_back(2);
+ return true;
+ }
+ return false;
+}
+
static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
// This attribute must be applied to a function declaration. The first
// argument to the attribute must be an identifier, the name of the resource,
@@ -1353,11 +1397,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
- // Normalize the argument, __foo__ becomes foo.
StringRef ModuleName = Module->getName();
- if (ModuleName.startswith("__") && ModuleName.endswith("__") &&
- ModuleName.size() > 4) {
- ModuleName = ModuleName.drop_front(2).drop_back(2);
+ if (normalizeName(ModuleName)) {
Module = &S.PP.getIdentifierTable().get(ModuleName);
}
@@ -1519,7 +1560,7 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<HotAttr>(S, D, Attr))
+ if (checkAttrMutualExclusion<HotAttr>(S, D, Attr.getRange(), Attr.getName()))
return;
D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context,
@@ -1527,7 +1568,7 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr))
+ if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr.getRange(), Attr.getName()))
return;
D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context,
@@ -1569,12 +1610,22 @@ static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CPlusPlus) {
S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
- << Attr.getName() << AttributeLangSupport::Cpp;
+ << Attr.getName() << AttributeLangSupport::Cpp;
return;
}
- D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ if (CommonAttr *CA = S.mergeCommonAttr(D, Attr.getRange(), Attr.getName(),
+ Attr.getAttributeSpellingListIndex()))
+ D->addAttr(CA);
+}
+
+static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
@@ -1613,7 +1664,7 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
!VD->getType()->isFunctionPointerType())) {
S.Diag(Attr.getLoc(),
Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
- : diag::warn_attribute_wrong_decl_type)
+ : diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionMethodOrBlock;
return;
}
@@ -1697,6 +1748,26 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleNotTailCalledAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ D->addAttr(::new (S.Context) NotTailCalledAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleDisableTailCallsAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<NakedAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ D->addAttr(::new (S.Context) DisableTailCallsAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasLocalStorage()) {
@@ -1825,12 +1896,24 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
VersionTuple Obsoleted,
bool IsUnavailable,
StringRef Message,
- bool Override,
+ AvailabilityMergeKind AMK,
unsigned AttrSpellingListIndex) {
VersionTuple MergedIntroduced = Introduced;
VersionTuple MergedDeprecated = Deprecated;
VersionTuple MergedObsoleted = Obsoleted;
bool FoundAny = false;
+ bool OverrideOrImpl = false;
+ switch (AMK) {
+ case AMK_None:
+ case AMK_Redeclaration:
+ OverrideOrImpl = false;
+ break;
+
+ case AMK_Override:
+ case AMK_ProtocolImplementation:
+ OverrideOrImpl = true;
+ break;
+ }
if (D->hasAttrs()) {
AttrVec &Attrs = D->getAttrs();
@@ -1847,30 +1930,46 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
continue;
}
+ // If there is an existing availability attribute for this platform that
+ // is explicit and the new one is implicit use the explicit one and
+ // discard the new implicit attribute.
+ if (OldAA->getRange().isValid() && Range.isInvalid()) {
+ return nullptr;
+ }
+
+ // If there is an existing attribute for this platform that is implicit
+ // and the new attribute is explicit then erase the old one and
+ // continue processing the attributes.
+ if (Range.isValid() && OldAA->getRange().isInvalid()) {
+ Attrs.erase(Attrs.begin() + i);
+ --e;
+ continue;
+ }
+
FoundAny = true;
VersionTuple OldIntroduced = OldAA->getIntroduced();
VersionTuple OldDeprecated = OldAA->getDeprecated();
VersionTuple OldObsoleted = OldAA->getObsoleted();
bool OldIsUnavailable = OldAA->getUnavailable();
- if (!versionsMatch(OldIntroduced, Introduced, Override) ||
- !versionsMatch(Deprecated, OldDeprecated, Override) ||
- !versionsMatch(Obsoleted, OldObsoleted, Override) ||
+ if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) ||
+ !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) ||
+ !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) ||
!(OldIsUnavailable == IsUnavailable ||
- (Override && !OldIsUnavailable && IsUnavailable))) {
- if (Override) {
+ (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) {
+ if (OverrideOrImpl) {
int Which = -1;
VersionTuple FirstVersion;
VersionTuple SecondVersion;
- if (!versionsMatch(OldIntroduced, Introduced, Override)) {
+ if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) {
Which = 0;
FirstVersion = OldIntroduced;
SecondVersion = Introduced;
- } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) {
+ } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) {
Which = 1;
FirstVersion = Deprecated;
SecondVersion = OldDeprecated;
- } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) {
+ } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) {
Which = 2;
FirstVersion = Obsoleted;
SecondVersion = OldObsoleted;
@@ -1879,15 +1978,20 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
if (Which == -1) {
Diag(OldAA->getLocation(),
diag::warn_mismatched_availability_override_unavail)
- << AvailabilityAttr::getPrettyPlatformName(Platform->getName());
+ << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
+ << (AMK == AMK_Override);
} else {
Diag(OldAA->getLocation(),
diag::warn_mismatched_availability_override)
<< Which
<< AvailabilityAttr::getPrettyPlatformName(Platform->getName())
- << FirstVersion.getAsString() << SecondVersion.getAsString();
+ << FirstVersion.getAsString() << SecondVersion.getAsString()
+ << (AMK == AMK_Override);
}
- Diag(Range.getBegin(), diag::note_overridden_method);
+ if (AMK == AMK_Override)
+ Diag(Range.getBegin(), diag::note_overridden_method);
+ else
+ Diag(Range.getBegin(), diag::note_protocol_method);
} else {
Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
Diag(Range.getBegin(), diag::note_previous_attribute);
@@ -1930,11 +2034,11 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
MergedObsoleted == Obsoleted)
return nullptr;
- // Only create a new attribute if !Override, but we want to do
+ // Only create a new attribute if !OverrideOrImpl, but we want to do
// the checking.
if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced,
MergedDeprecated, MergedObsoleted) &&
- !Override) {
+ !OverrideOrImpl) {
return ::new (Context) AvailabilityAttr(Range, Context, Platform,
Introduced, Deprecated,
Obsoleted, IsUnavailable, Message,
@@ -1975,10 +2079,78 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
Deprecated.Version,
Obsoleted.Version,
IsUnavailable, Str,
- /*Override=*/false,
+ Sema::AMK_None,
Index);
if (NewAttr)
D->addAttr(NewAttr);
+
+ // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning
+ // matches before the start of the watchOS platform.
+ if (S.Context.getTargetInfo().getTriple().isWatchOS()) {
+ IdentifierInfo *NewII = nullptr;
+ if (II->getName() == "ios")
+ NewII = &S.Context.Idents.get("watchos");
+ else if (II->getName() == "ios_app_extension")
+ NewII = &S.Context.Idents.get("watchos_app_extension");
+
+ if (NewII) {
+ auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple {
+ if (Version.empty())
+ return Version;
+ auto Major = Version.getMajor();
+ auto NewMajor = Major >= 9 ? Major - 7 : 0;
+ if (NewMajor >= 2) {
+ if (Version.getMinor().hasValue()) {
+ if (Version.getSubminor().hasValue())
+ return VersionTuple(NewMajor, Version.getMinor().getValue(),
+ Version.getSubminor().getValue());
+ else
+ return VersionTuple(NewMajor, Version.getMinor().getValue());
+ }
+ }
+
+ return VersionTuple(2, 0);
+ };
+
+ auto NewIntroduced = adjustWatchOSVersion(Introduced.Version);
+ auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version);
+ auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
+
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND,
+ SourceRange(),
+ NewII,
+ NewIntroduced,
+ NewDeprecated,
+ NewObsoleted,
+ IsUnavailable, Str,
+ Sema::AMK_None,
+ Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+ }
+ } else if (S.Context.getTargetInfo().getTriple().isTvOS()) {
+ // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning
+ // matches before the start of the tvOS platform.
+ IdentifierInfo *NewII = nullptr;
+ if (II->getName() == "ios")
+ NewII = &S.Context.Idents.get("tvos");
+ else if (II->getName() == "ios_app_extension")
+ NewII = &S.Context.Idents.get("tvos_app_extension");
+
+ if (NewII) {
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND,
+ SourceRange(),
+ NewII,
+ Introduced.Version,
+ Deprecated.Version,
+ Obsoleted.Version,
+ IsUnavailable, Str,
+ Sema::AMK_None,
+ Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+ }
+ }
}
template <class T>
@@ -2492,17 +2664,17 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, IdxExpr, Idx))
return;
- // make sure the format string is really a string
+ // Make sure the format string is really a string.
QualType Ty = getFunctionOrMethodParamType(D, Idx);
- bool not_nsstring_type = !isNSStringType(Ty, S.Context);
- if (not_nsstring_type &&
+ bool NotNSStringTy = !isNSStringType(Ty, S.Context);
+ if (NotNSStringTy &&
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
- << (not_nsstring_type ? "a string type" : "an NSString")
- << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
+ << "a string type" << IdxExpr->getSourceRange()
+ << getFunctionOrMethodParamRange(D, 0);
return;
}
Ty = getFunctionOrMethodResultType(D);
@@ -2511,7 +2683,7 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
- << (not_nsstring_type ? "string type" : "NSString")
+ << (NotNSStringTy ? "string type" : "NSString")
<< IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
return;
}
@@ -2588,7 +2760,7 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,
if (prioritynum < 101 || prioritynum > 65535) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
- << E->getSourceRange();
+ << E->getSourceRange() << Attr.getName() << 101 << 65535;
Attr.setInvalid();
return;
}
@@ -2635,9 +2807,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
StringRef Format = II->getName();
- // Normalize the argument, __foo__ becomes foo.
- if (Format.startswith("__") && Format.endswith("__")) {
- Format = Format.substr(2, Format.size() - 4);
+ if (normalizeName(Format)) {
// If we've modified the string name, we need a new identifier for it.
II = &S.Context.Idents.get(Format);
}
@@ -2858,7 +3028,7 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
}
if (!E->isValueDependent()) {
- llvm::APSInt Alignment(32);
+ llvm::APSInt Alignment;
ExprResult ICE
= VerifyIntegerConstantExpression(E, &Alignment,
diag::err_align_value_attribute_argument_not_int,
@@ -2972,7 +3142,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
}
// FIXME: Cache the number on the Attr object?
- llvm::APSInt Alignment(32);
+ llvm::APSInt Alignment;
ExprResult ICE
= VerifyIntegerConstantExpression(E, &Alignment,
diag::err_aligned_attribute_argument_not_int,
@@ -2980,42 +3150,44 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
if (ICE.isInvalid())
return;
+ uint64_t AlignVal = Alignment.getZExtValue();
+
// C++11 [dcl.align]p2:
// -- if the constant expression evaluates to zero, the alignment
// specifier shall have no effect
// C11 6.7.5p6:
// An alignment specification of zero has no effect.
if (!(TmpAttr.isAlignas() && !Alignment)) {
- if(!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
+ if (!llvm::isPowerOf2_64(AlignVal)) {
Diag(AttrLoc, diag::err_alignment_not_power_of_two)
<< E->getSourceRange();
return;
}
- if (Context.getTargetInfo().isTLSSupported()) {
- if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->getTLSKind()) {
- CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
- if (Alignment.getSExtValue() > MaxAlignChars.getQuantity()) {
- Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
- << (unsigned)Alignment.getZExtValue() << VD
- << (unsigned)MaxAlignChars.getQuantity();
- return;
- }
- }
- }
- }
- }
}
// Alignment calculations can wrap around if it's greater than 2**28.
- unsigned MaxValidAlignment = TmpAttr.isDeclspec() ? 8192 : 268435456;
- if (Alignment.getZExtValue() > MaxValidAlignment) {
+ unsigned MaxValidAlignment =
+ Context.getTargetInfo().getTriple().isOSBinFormatCOFF() ? 8192
+ : 268435456;
+ if (AlignVal > MaxValidAlignment) {
Diag(AttrLoc, diag::err_attribute_aligned_too_great) << MaxValidAlignment
<< E->getSourceRange();
return;
}
+ if (Context.getTargetInfo().isTLSSupported()) {
+ unsigned MaxTLSAlign =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
+ .getQuantity();
+ auto *VD = dyn_cast<VarDecl>(D);
+ if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD &&
+ VD->getTLSKind() != VarDecl::TLS_None) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)AlignVal << VD << MaxTLSAlign;
+ return;
+ }
+ }
+
AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true,
ICE.get(), SpellingListIndex);
AA->setPackExpansion(IsPackExpansion);
@@ -3098,40 +3270,31 @@ bool Sema::checkMSInheritanceAttrOnDefinition(
return true;
}
-/// handleModeAttr - This attribute modifies the width of a decl with primitive
-/// type.
-///
-/// Despite what would be logical, the mode attribute is a decl attribute, not a
-/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
-/// HImode, not an intermediate pointer.
-static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // This attribute isn't documented, but glibc uses it. It changes
- // the width of an int or unsigned int to the specified size.
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
- << AANT_ArgumentIdentifier;
- return;
- }
-
- IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
- StringRef Str = Name->getName();
-
- // Normalize the attribute name, __foo__ becomes foo.
- if (Str.startswith("__") && Str.endswith("__"))
- Str = Str.substr(2, Str.size() - 4);
-
- unsigned DestWidth = 0;
- bool IntegerMode = true;
- bool ComplexMode = false;
+/// parseModeAttrArg - Parses attribute mode string and returns parsed type
+/// attribute.
+static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
+ bool &IntegerMode, bool &ComplexMode) {
switch (Str.size()) {
case 2:
switch (Str[0]) {
- case 'Q': DestWidth = 8; break;
- case 'H': DestWidth = 16; break;
- case 'S': DestWidth = 32; break;
- case 'D': DestWidth = 64; break;
- case 'X': DestWidth = 96; break;
- case 'T': DestWidth = 128; break;
+ case 'Q':
+ DestWidth = 8;
+ break;
+ case 'H':
+ DestWidth = 16;
+ break;
+ case 'S':
+ DestWidth = 32;
+ break;
+ case 'D':
+ DestWidth = 64;
+ break;
+ case 'X':
+ DestWidth = 96;
+ break;
+ case 'T':
+ DestWidth = 128;
+ break;
}
if (Str[1] == 'F') {
IntegerMode = false;
@@ -3159,6 +3322,52 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
DestWidth = S.Context.getTargetInfo().getUnwindWordWidth();
break;
}
+}
+
+/// handleModeAttr - This attribute modifies the width of a decl with primitive
+/// type.
+///
+/// Despite what would be logical, the mode attribute is a decl attribute, not a
+/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
+/// HImode, not an intermediate pointer.
+static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // This attribute isn't documented, but glibc uses it. It changes
+ // the width of an int or unsigned int to the specified size.
+ if (!Attr.isArgIdent(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
+ StringRef Str = Name->getName();
+
+ normalizeName(Str);
+
+ unsigned DestWidth = 0;
+ bool IntegerMode = true;
+ bool ComplexMode = false;
+ llvm::APInt VectorSize(64, 0);
+ if (Str.size() >= 4 && Str[0] == 'V') {
+ // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
+ size_t StrSize = Str.size();
+ size_t VectorStringLength = 0;
+ while ((VectorStringLength + 1) < StrSize &&
+ isdigit(Str[VectorStringLength + 1]))
+ ++VectorStringLength;
+ if (VectorStringLength &&
+ !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
+ VectorSize.isPowerOf2()) {
+ parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth,
+ IntegerMode, ComplexMode);
+ S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated);
+ } else {
+ VectorSize = 0;
+ }
+ }
+
+ if (!VectorSize)
+ parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode);
QualType OldTy;
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
@@ -3217,7 +3426,10 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
QualType NewTy = NewElemTy;
- if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
+ if (VectorSize.getBoolValue()) {
+ NewTy = S.Context.getVectorType(NewTy, VectorSize.getZExtValue(),
+ VectorType::GenericVector);
+ } else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
// Complex machine mode does not support base vector types.
if (ComplexMode) {
S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type);
@@ -3280,6 +3492,42 @@ AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
AttrSpellingListIndex);
}
+CommonAttr *Sema::mergeCommonAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex) {
+ if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, Range, Ident))
+ return nullptr;
+
+ return ::new (Context) CommonAttr(Range, Context, AttrSpellingListIndex);
+}
+
+InternalLinkageAttr *
+Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex) {
+ if (auto VD = dyn_cast<VarDecl>(D)) {
+ // Attribute applies to Var but not any subclass of it (like ParmVar,
+ // ImplicitParm or VarTemplateSpecialization).
+ if (VD->getKind() != Decl::Var) {
+ Diag(Range.getBegin(), diag::warn_attribute_wrong_decl_type)
+ << Ident << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
+ : ExpectedVariableOrFunction);
+ return nullptr;
+ }
+ // Attribute does not apply to non-static local variables.
+ if (VD->hasLocalStorage()) {
+ Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
+ return nullptr;
+ }
+ }
+
+ if (checkAttrMutualExclusion<CommonAttr>(*this, D, Range, Ident))
+ return nullptr;
+
+ return ::new (Context)
+ InternalLinkageAttr(Range, Context, AttrSpellingListIndex);
+}
+
MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex) {
if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
@@ -3316,6 +3564,10 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
static void handleAlwaysInlineAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
D, Attr.getRange(), Attr.getName(),
Attr.getAttributeSpellingListIndex()))
@@ -3349,6 +3601,7 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
D->addAttr(::new (S.Context)
CUDAGlobalAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
+
}
static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -3645,7 +3898,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx);
if (!BufferTy->isPointerType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
- << Attr.getName();
+ << Attr.getName() << 0;
}
}
@@ -3898,7 +4151,8 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr))
+ if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
return;
D->addAttr(::new (S.Context)
@@ -3908,7 +4162,8 @@ static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
static void handleCFUnknownTransferAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr))
+ if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
return;
D->addAttr(::new (S.Context)
@@ -4231,14 +4486,86 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D,
D->addAttr(UsedAttr::CreateImplicit(S.Context));
}
+static void handleMipsInterruptAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // Only one optional argument permitted.
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ StringRef Str;
+ SourceLocation ArgLoc;
+
+ if (Attr.getNumArgs() == 0)
+ Str = "";
+ else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
+ return;
+
+ // Semantic checks for a function with the 'interrupt' attribute for MIPS:
+ // a) Must be a function.
+ // b) Must have no parameters.
+ // c) Must have the 'void' return type.
+ // d) Cannot have the 'mips16' attribute, as that instruction set
+ // lacks the 'eret' instruction.
+ // e) The attribute itself must either have no argument or one of the
+ // valid interrupt types, see [MipsInterruptDocs].
+
+ if (!isFunctionOrMethod(D)) {
+ S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
+ << "'interrupt'" << ExpectedFunctionOrMethod;
+ return;
+ }
+
+ if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
+ S.Diag(D->getLocation(), diag::warn_mips_interrupt_attribute)
+ << 0;
+ return;
+ }
+
+ if (!getFunctionOrMethodResultType(D)->isVoidType()) {
+ S.Diag(D->getLocation(), diag::warn_mips_interrupt_attribute)
+ << 1;
+ return;
+ }
+
+ if (checkAttrMutualExclusion<Mips16Attr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ MipsInterruptAttr::InterruptType Kind;
+ if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << Attr.getName() << "'" + std::string(Str) + "'";
+ return;
+ }
+
+ D->addAttr(::new (S.Context) MipsInterruptAttr(
+ Attr.getLoc(), S.Context, Kind, Attr.getAttributeSpellingListIndex()));
+}
+
static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Dispatch the interrupt attribute based on the current target.
if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430)
handleMSP430InterruptAttr(S, D, Attr);
+ else if (S.Context.getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::mipsel ||
+ S.Context.getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::mips)
+ handleMipsInterruptAttr(S, D, Attr);
else
handleARMInterruptAttr(S, D, Attr);
}
+static void handleMips16Attribute(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<MipsInterruptAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ handleSimpleAttribute<Mips16Attr>(S, D, Attr);
+}
+
static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
uint32_t NumRegs;
@@ -4334,6 +4661,14 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
}
}
+ if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ MD->getParent()->isLambda()) {
+ S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A.getName();
+ return;
+ }
+ }
+
unsigned Index = A.getAttributeSpellingListIndex();
Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport
? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
@@ -4509,8 +4844,10 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
+ StringRef AttrName = Attr.getName()->getName();
+ normalizeName(AttrName);
std::string SanitizerName =
- llvm::StringSwitch<std::string>(Attr.getName()->getName())
+ llvm::StringSwitch<std::string>(AttrName)
.Case("no_address_safety_analysis", "address")
.Case("no_sanitize_address", "address")
.Case("no_sanitize_thread", "thread")
@@ -4520,6 +4857,14 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleInternalLinkageAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (InternalLinkageAttr *Internal =
+ S.mergeInternalLinkageAttr(D, Attr.getRange(), Attr.getName(),
+ Attr.getAttributeSpellingListIndex()))
+ D->addAttr(Internal);
+}
+
/// Handles semantic checking for features that are common to all attributes,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
@@ -4583,7 +4928,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
// which do not apply to the current target architecture are treated as
// though they were unknown attributes.
if (Attr.getKind() == AttributeList::UnknownAttribute ||
- !Attr.existsInTarget(S.Context.getTargetInfo().getTriple())) {
+ !Attr.existsInTarget(S.Context.getTargetInfo())) {
S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute()
? diag::warn_unhandled_ms_attribute_ignored
: diag::warn_unknown_attribute_ignored)
@@ -4610,7 +4955,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleDLLAttr(S, D, Attr);
break;
case AttributeList::AT_Mips16:
- handleSimpleAttribute<Mips16Attr>(S, D, Attr);
+ handleMips16Attribute(S, D, Attr);
break;
case AttributeList::AT_NoMips16:
handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
@@ -4663,6 +5008,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_CUDAConstant:
handleSimpleAttribute<CUDAConstantAttr>(S, D, Attr);
break;
+ case AttributeList::AT_PassObjectSize:
+ handlePassObjectSizeAttr(S, D, Attr);
+ break;
case AttributeList::AT_Constructor:
handleConstructorAttr(S, D, Attr);
break;
@@ -4723,6 +5071,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_Mode:
handleModeAttr(S, D, Attr);
break;
+ case AttributeList::AT_NoAlias:
+ handleSimpleAttribute<NoAliasAttr>(S, D, Attr);
+ break;
case AttributeList::AT_NoCommon:
handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
break;
@@ -4754,7 +5105,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleHotAttr(S, D, Attr);
break;
case AttributeList::AT_Naked:
- handleSimpleAttribute<NakedAttr>(S, D, Attr);
+ handleNakedAttr(S, D, Attr);
break;
case AttributeList::AT_NoReturn:
handleNoReturnAttr(S, D, Attr);
@@ -4874,6 +5225,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ReturnsTwice:
handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr);
break;
+ case AttributeList::AT_NotTailCalled:
+ handleNotTailCalledAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_DisableTailCalls:
+ handleDisableTailCallsAttr(S, D, Attr);
+ break;
case AttributeList::AT_Used:
handleUsedAttr(S, D, Attr);
break;
@@ -4958,6 +5315,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_OpenCLImageAccess:
handleSimpleAttribute<OpenCLImageAccessAttr>(S, D, Attr);
break;
+ case AttributeList::AT_InternalLinkage:
+ handleInternalLinkageAttr(S, D, Attr);
+ break;
// Microsoft attributes:
case AttributeList::AT_MSNoVTable:
@@ -5299,26 +5659,50 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
}
/// Is the given declaration allowed to use a forbidden type?
-static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) {
+/// If so, it'll still be annotated with an attribute that makes it
+/// illegal to actually use.
+static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
+ const DelayedDiagnostic &diag,
+ UnavailableAttr::ImplicitReason &reason) {
// Private ivars are always okay. Unfortunately, people don't
// always properly make their ivars private, even in system headers.
// Plus we need to make fields okay, too.
- // Function declarations in sys headers will be marked unavailable.
if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) &&
!isa<FunctionDecl>(decl))
return false;
- // Require it to be declared in a system header.
- return S.Context.getSourceManager().isInSystemHeader(decl->getLocation());
+ // Silently accept unsupported uses of __weak in both user and system
+ // declarations when it's been disabled, for ease of integration with
+ // -fno-objc-arc files. We do have to take some care against attempts
+ // to define such things; for now, we've only done that for ivars
+ // and properties.
+ if ((isa<ObjCIvarDecl>(decl) || isa<ObjCPropertyDecl>(decl))) {
+ if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled ||
+ diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) {
+ reason = UnavailableAttr::IR_ForbiddenWeak;
+ return true;
+ }
+ }
+
+ // Allow all sorts of things in system headers.
+ if (S.Context.getSourceManager().isInSystemHeader(decl->getLocation())) {
+ // Currently, all the failures dealt with this way are due to ARC
+ // restrictions.
+ reason = UnavailableAttr::IR_ARCForbiddenType;
+ return true;
+ }
+
+ return false;
}
/// Handle a delayed forbidden-type diagnostic.
static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
Decl *decl) {
- if (decl && isForbiddenTypeAllowed(S, decl)) {
- decl->addAttr(UnavailableAttr::CreateImplicit(S.Context,
- "this system declaration uses an unsupported type",
- diag.Loc));
+ auto reason = UnavailableAttr::IR_None;
+ if (decl && isForbiddenTypeAllowed(S, decl, diag, reason)) {
+ assert(reason && "didn't set reason?");
+ decl->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", reason,
+ diag.Loc));
return;
}
if (S.getLangOpts().ObjCAutoRefCount)
@@ -5371,6 +5755,7 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
bool ObjCPropertyAccess) {
// Diagnostics for deprecated or unavailable.
unsigned diag, diag_message, diag_fwdclass_message;
+ unsigned diag_available_here = diag::note_availability_specified_here;
// Matches 'diag::note_property_attribute' options.
unsigned property_note_select;
@@ -5400,6 +5785,50 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
diag_fwdclass_message = diag::warn_unavailable_fwdclass_message;
property_note_select = /* unavailable */ 1;
available_here_select_kind = /* unavailable */ 0;
+
+ if (auto attr = D->getAttr<UnavailableAttr>()) {
+ if (attr->isImplicit() && attr->getImplicitReason()) {
+ // Most of these failures are due to extra restrictions in ARC;
+ // reflect that in the primary diagnostic when applicable.
+ auto flagARCError = [&] {
+ if (S.getLangOpts().ObjCAutoRefCount &&
+ S.getSourceManager().isInSystemHeader(D->getLocation()))
+ diag = diag::err_unavailable_in_arc;
+ };
+
+ switch (attr->getImplicitReason()) {
+ case UnavailableAttr::IR_None: break;
+
+ case UnavailableAttr::IR_ARCForbiddenType:
+ flagARCError();
+ diag_available_here = diag::note_arc_forbidden_type;
+ break;
+
+ case UnavailableAttr::IR_ForbiddenWeak:
+ if (S.getLangOpts().ObjCWeakRuntime)
+ diag_available_here = diag::note_arc_weak_disabled;
+ else
+ diag_available_here = diag::note_arc_weak_no_runtime;
+ break;
+
+ case UnavailableAttr::IR_ARCForbiddenConversion:
+ flagARCError();
+ diag_available_here = diag::note_performs_forbidden_arc_conversion;
+ break;
+
+ case UnavailableAttr::IR_ARCInitReturnsUnrelated:
+ flagARCError();
+ diag_available_here = diag::note_arc_init_returns_unrelated;
+ break;
+
+ case UnavailableAttr::IR_ARCFieldWithOwnership:
+ flagARCError();
+ diag_available_here = diag::note_arc_field_with_ownership;
+ break;
+ }
+ }
+ }
+
break;
case Sema::AD_Partial:
@@ -5426,7 +5855,7 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
- S.Diag(D->getLocation(), diag::note_availability_specified_here)
+ S.Diag(D->getLocation(), diag_available_here)
<< D << available_here_select_kind;
if (K == Sema::AD_Partial)
S.Diag(Loc, diag::note_partial_availability_silence) << D;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 0d7cbf45e525..3f6c6b00d902 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -162,34 +162,31 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
+ // If we have a throw-all spec at this point, ignore the function.
+ if (ComputedEST == EST_None)
+ return;
+
+ switch(EST) {
// If this function can throw any exceptions, make a note of that.
- if (EST == EST_MSAny || EST == EST_None) {
+ case EST_MSAny:
+ case EST_None:
ClearExceptions();
ComputedEST = EST;
return;
- }
-
// FIXME: If the call to this decl is using any of its default arguments, we
// need to search them for potentially-throwing calls.
-
// If this function has a basic noexcept, it doesn't affect the outcome.
- if (EST == EST_BasicNoexcept)
- return;
-
- // If we have a throw-all spec at this point, ignore the function.
- if (ComputedEST == EST_None)
+ case EST_BasicNoexcept:
return;
-
// If we're still at noexcept(true) and there's a nothrow() callee,
// change to that specification.
- if (EST == EST_DynamicNone) {
+ case EST_DynamicNone:
if (ComputedEST == EST_BasicNoexcept)
ComputedEST = EST_DynamicNone;
return;
- }
-
// Check out noexcept specs.
- if (EST == EST_ComputedNoexcept) {
+ case EST_ComputedNoexcept:
+ {
FunctionProtoType::NoexceptResult NR =
Proto->getNoexceptSpec(Self->Context);
assert(NR != FunctionProtoType::NR_NoNoexcept &&
@@ -197,7 +194,6 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
assert(NR != FunctionProtoType::NR_Dependent &&
"Should not generate implicit declarations for dependent cases, "
"and don't know how to handle them anyway.");
-
// noexcept(false) -> no spec on the new function
if (NR == FunctionProtoType::NR_Throw) {
ClearExceptions();
@@ -206,7 +202,9 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
// noexcept(true) won't change anything either.
return;
}
-
+ default:
+ break;
+ }
assert(EST == EST_Dynamic && "EST case not considered earlier.");
assert(ComputedEST != EST_None &&
"Shouldn't collect exceptions when throw-all is guaranteed.");
@@ -1232,9 +1230,9 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
Diag(Dcl->getLocation(),
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
: diag::err_constexpr_body_no_return);
- return OK;
- }
- if (ReturnStmts.size() > 1) {
+ if (!OK)
+ return false;
+ } else if (ReturnStmts.size() > 1) {
Diag(ReturnStmts.back(),
getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_body_multiple_return
@@ -1555,9 +1553,9 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
/// \brief Performs the actual work of attaching the given base class
/// specifiers to a C++ class.
-bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
- unsigned NumBases) {
- if (NumBases == 0)
+bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
+ MutableArrayRef<CXXBaseSpecifier *> Bases) {
+ if (Bases.empty())
return false;
// Used to keep track of which base types we have already seen, so
@@ -1573,7 +1571,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
// Copy non-redundant base specifiers into permanent storage.
unsigned NumGoodBases = 0;
bool Invalid = false;
- for (unsigned idx = 0; idx < NumBases; ++idx) {
+ for (unsigned idx = 0; idx < Bases.size(); ++idx) {
QualType NewBaseType
= Context.getCanonicalType(Bases[idx]->getType());
NewBaseType = NewBaseType.getLocalUnqualifiedType();
@@ -1599,7 +1597,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
Bases[NumGoodBases++] = Bases[idx];
// Note this base's direct & indirect bases, if there could be ambiguity.
- if (NumBases > 1)
+ if (Bases.size() > 1)
NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType);
if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
@@ -1621,7 +1619,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
}
// Attach the remaining base class specifiers to the derived class.
- Class->setBases(Bases, NumGoodBases);
+ Class->setBases(Bases.data(), NumGoodBases);
for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
// Check whether this direct base is inaccessible due to ambiguity.
@@ -1656,21 +1654,21 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
/// ActOnBaseSpecifiers - Attach the given base specifiers to the
/// class, after checking whether there are any duplicate base
/// classes.
-void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases,
- unsigned NumBases) {
- if (!ClassDecl || !Bases || !NumBases)
+void Sema::ActOnBaseSpecifiers(Decl *ClassDecl,
+ MutableArrayRef<CXXBaseSpecifier *> Bases) {
+ if (!ClassDecl || Bases.empty())
return;
AdjustDeclIfTemplate(ClassDecl);
- AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases, NumBases);
+ AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases);
}
/// \brief Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
-bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
+bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
if (!getLangOpts().CPlusPlus)
return false;
-
+
CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
if (!DerivedRD)
return false;
@@ -1684,13 +1682,18 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl())
return false;
- // FIXME: instantiate DerivedRD if necessary. We need a PoI for this.
- return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
+ // FIXME: In a modules build, do we need the entire path to be visible for us
+ // to be able to use the inheritance relationship?
+ if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
+ return false;
+
+ return DerivedRD->isDerivedFrom(BaseRD);
}
/// \brief Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
-bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
+bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
+ CXXBasePaths &Paths) {
if (!getLangOpts().CPlusPlus)
return false;
@@ -1702,6 +1705,9 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
if (!BaseRD)
return false;
+ if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
+ return false;
+
return DerivedRD->isDerivedFrom(BaseRD, Paths);
}
@@ -1749,7 +1755,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
// explore multiple paths to determine if there is an ambiguity.
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
- bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths);
+ bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
assert(DerivationOkay &&
"Can only be used with a derived-to-base conversion");
(void)DerivationOkay;
@@ -1783,7 +1789,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
// performance isn't as much of an issue.
Paths.clear();
Paths.setRecordingPaths(true);
- bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
+ bool StillOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
assert(StillOkay && "Can only be used with a derived-to-base conversion");
(void)StillOkay;
@@ -2759,7 +2765,8 @@ static bool FindBaseInitializer(Sema &SemaRef,
// virtual base class.
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
- if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl),
+ if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(),
+ SemaRef.Context.getTypeDeclType(ClassDecl),
BaseType, Paths)) {
for (CXXBasePaths::paths_iterator Path = Paths.begin();
Path != Paths.end(); ++Path) {
@@ -2982,10 +2989,15 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (BaseType.isNull()) {
BaseType = Context.getTypeDeclType(TyD);
MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false);
- if (SS.isSet())
- // FIXME: preserve source range information
+ if (SS.isSet()) {
BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(),
BaseType);
+ TInfo = Context.CreateTypeSourceInfo(BaseType);
+ ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>();
+ TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc);
+ TL.setElaboratedKeywordLoc(SourceLocation());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ }
}
}
@@ -3483,7 +3495,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
/*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
MemberLookup,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S*/nullptr);
if (CtorArg.isInvalid())
return true;
@@ -4140,7 +4153,7 @@ static void DiagnoseBaseOrMemInitializerOrder(
if (InitKey == IdealInitKeys[IdealIndex])
break;
- assert(IdealIndex != NumIdealInits &&
+ assert(IdealIndex < NumIdealInits &&
"initializer not found in initializer list");
}
@@ -4407,64 +4420,35 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
}
}
-bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
- unsigned DiagID, AbstractDiagSelID SelID) {
- class NonAbstractTypeDiagnoser : public TypeDiagnoser {
- unsigned DiagID;
- AbstractDiagSelID SelID;
-
- public:
- NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID)
- : TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { }
-
- void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
- if (Suppressed) return;
- if (SelID == -1)
- S.Diag(Loc, DiagID) << T;
- else
- S.Diag(Loc, DiagID) << SelID << T;
- }
- } Diagnoser(DiagID, SelID);
-
- return RequireNonAbstractType(Loc, T, Diagnoser);
-}
-
-bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser) {
+bool Sema::isAbstractType(SourceLocation Loc, QualType T) {
if (!getLangOpts().CPlusPlus)
return false;
- if (const ArrayType *AT = Context.getAsArrayType(T))
- return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser);
-
- if (const PointerType *PT = T->getAs<PointerType>()) {
- // Find the innermost pointer type.
- while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>())
- PT = T;
-
- if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
- return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser);
- }
-
- const RecordType *RT = T->getAs<RecordType>();
- if (!RT)
+ const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl();
+ if (!RD)
return false;
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ // FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a
+ // class template specialization here, but doing so breaks a lot of code.
// We can't answer whether something is abstract until it has a
- // definition. If it's currently being defined, we'll walk back
+ // definition. If it's currently being defined, we'll walk back
// over all the declarations when we have a full definition.
const CXXRecordDecl *Def = RD->getDefinition();
if (!Def || Def->isBeingDefined())
return false;
- if (!RD->isAbstract())
+ return RD->isAbstract();
+}
+
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser) {
+ if (!isAbstractType(Loc, T))
return false;
+ T = Context.getBaseElementType(T);
Diagnoser.diagnose(*this, Loc, T);
- DiagnoseAbstractType(RD);
-
+ DiagnoseAbstractType(T->getAsCXXRecordDecl());
return true;
}
@@ -4684,6 +4668,60 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
}
}
+static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
+ Attr *ClassAttr = getDLLAttr(Class);
+ if (!ClassAttr)
+ return;
+
+ assert(ClassAttr->getKind() == attr::DLLExport);
+
+ TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
+
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ // Don't go any further if this is just an explicit instantiation
+ // declaration.
+ return;
+
+ for (Decl *Member : Class->decls()) {
+ auto *MD = dyn_cast<CXXMethodDecl>(Member);
+ if (!MD)
+ continue;
+
+ if (Member->getAttr<DLLExportAttr>()) {
+ if (MD->isUserProvided()) {
+ // Instantiate non-default class member functions ...
+
+ // .. except for certain kinds of template specializations.
+ if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
+ continue;
+
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+
+ // The function will be passed to the consumer when its definition is
+ // encountered.
+ } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
+ MD->isCopyAssignmentOperator() ||
+ MD->isMoveAssignmentOperator()) {
+ // Synthesize and instantiate non-trivial implicit methods, explicitly
+ // defaulted methods, and the copy and move assignment operators. The
+ // latter are exported even if they are trivial, because the address of
+ // an operator can be taken and should compare equal accross libraries.
+ DiagnosticErrorTrap Trap(S.Diags);
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+ if (Trap.hasErrorOccurred()) {
+ S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
+ << Class->getName() << !S.getLangOpts().CPlusPlus11;
+ break;
+ }
+
+ // There is no later point when we will see the definition of this
+ // function, so pass it to the consumer now.
+ S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
+ }
+ }
+ }
+}
+
/// \brief Check class-level dllimport/dllexport attribute.
void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
@@ -4785,45 +4823,10 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
}
-
- if (MD && ClassExported) {
- if (TSK == TSK_ExplicitInstantiationDeclaration)
- // Don't go any further if this is just an explicit instantiation
- // declaration.
- continue;
-
- if (MD->isUserProvided()) {
- // Instantiate non-default class member functions ...
-
- // .. except for certain kinds of template specializations.
- if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
- continue;
-
- MarkFunctionReferenced(Class->getLocation(), MD);
-
- // The function will be passed to the consumer when its definition is
- // encountered.
- } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
- MD->isCopyAssignmentOperator() ||
- MD->isMoveAssignmentOperator()) {
- // Synthesize and instantiate non-trivial implicit methods, explicitly
- // defaulted methods, and the copy and move assignment operators. The
- // latter are exported even if they are trivial, because the address of
- // an operator can be taken and should compare equal accross libraries.
- DiagnosticErrorTrap Trap(Diags);
- MarkFunctionReferenced(Class->getLocation(), MD);
- if (Trap.hasErrorOccurred()) {
- Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
- << Class->getName() << !getLangOpts().CPlusPlus11;
- break;
- }
-
- // There is no later point when we will see the definition of this
- // function, so pass it to the consumer now.
- Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
- }
- }
}
+
+ if (ClassExported)
+ DelayedDllExportClasses.push_back(Class);
}
/// \brief Perform propagation of DLL attributes from a derived class to a
@@ -5623,7 +5626,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
/// having a particular direct or virtual base class.
bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) {
CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl();
- return shouldDeleteForClassSubobject(BaseClass, Base, 0);
+ // If program is correct, BaseClass cannot be null, but if it is, the error
+ // must be reported elsewhere.
+ return BaseClass && shouldDeleteForClassSubobject(BaseClass, Base, 0);
}
/// Check whether we should delete a special member function due to the class
@@ -6270,77 +6275,75 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
return true;
}
-/// \brief Data used with FindHiddenVirtualMethod
namespace {
- struct FindHiddenVirtualMethodData {
- Sema *S;
- CXXMethodDecl *Method;
- llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
- SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
- };
-}
-
-/// \brief Check whether any most overriden method from MD in Methods
-static bool CheckMostOverridenMethods(const CXXMethodDecl *MD,
- const llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
- if (MD->size_overridden_methods() == 0)
- return Methods.count(MD->getCanonicalDecl());
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E; ++I)
- if (CheckMostOverridenMethods(*I, Methods))
- return true;
- return false;
-}
+struct FindHiddenVirtualMethod {
+ Sema *S;
+ CXXMethodDecl *Method;
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
+ SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
-/// \brief Member lookup function that determines whether a given C++
-/// method overloads virtual methods in a base class without overriding any,
-/// to be used with CXXRecordDecl::lookupInBases().
-static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
-
- FindHiddenVirtualMethodData &Data
- = *static_cast<FindHiddenVirtualMethodData*>(UserData);
-
- DeclarationName Name = Data.Method->getDeclName();
- assert(Name.getNameKind() == DeclarationName::Identifier);
-
- bool foundSameNameMethod = false;
- SmallVector<CXXMethodDecl *, 8> overloadedMethods;
- for (Path.Decls = BaseRecord->lookup(Name);
- !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- MD = MD->getCanonicalDecl();
- foundSameNameMethod = true;
- // Interested only in hidden virtual methods.
- if (!MD->isVirtual())
- continue;
- // If the method we are checking overrides a method from its base
- // don't warn about the other overloaded methods. Clang deviates from GCC
- // by only diagnosing overloads of inherited virtual functions that do not
- // override any other virtual functions in the base. GCC's
- // -Woverloaded-virtual diagnoses any derived function hiding a virtual
- // function from a base class. These cases may be better served by a
- // warning (not specific to virtual functions) on call sites when the call
- // would select a different function from the base class, were it visible.
- // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
- if (!Data.S->IsOverload(Data.Method, MD, false))
+private:
+ /// Check whether any most overriden method from MD in Methods
+ static bool CheckMostOverridenMethods(
+ const CXXMethodDecl *MD,
+ const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) {
+ if (MD->size_overridden_methods() == 0)
+ return Methods.count(MD->getCanonicalDecl());
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods();
+ I != E; ++I)
+ if (CheckMostOverridenMethods(*I, Methods))
return true;
- // Collect the overload only if its hidden.
- if (!CheckMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods))
- overloadedMethods.push_back(MD);
- }
+ return false;
}
- if (foundSameNameMethod)
- Data.OverloadedMethods.append(overloadedMethods.begin(),
- overloadedMethods.end());
- return foundSameNameMethod;
-}
+public:
+ /// Member lookup function that determines whether a given C++
+ /// method overloads virtual methods in a base class without overriding any,
+ /// to be used with CXXRecordDecl::lookupInBases().
+ bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ RecordDecl *BaseRecord =
+ Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ DeclarationName Name = Method->getDeclName();
+ assert(Name.getNameKind() == DeclarationName::Identifier);
+
+ bool foundSameNameMethod = false;
+ SmallVector<CXXMethodDecl *, 8> overloadedMethods;
+ for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
+ Path.Decls = Path.Decls.slice(1)) {
+ NamedDecl *D = Path.Decls.front();
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ MD = MD->getCanonicalDecl();
+ foundSameNameMethod = true;
+ // Interested only in hidden virtual methods.
+ if (!MD->isVirtual())
+ continue;
+ // If the method we are checking overrides a method from its base
+ // don't warn about the other overloaded methods. Clang deviates from
+ // GCC by only diagnosing overloads of inherited virtual functions that
+ // do not override any other virtual functions in the base. GCC's
+ // -Woverloaded-virtual diagnoses any derived function hiding a virtual
+ // function from a base class. These cases may be better served by a
+ // warning (not specific to virtual functions) on call sites when the
+ // call would select a different function from the base class, were it
+ // visible.
+ // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
+ if (!S->IsOverload(Method, MD, false))
+ return true;
+ // Collect the overload only if its hidden.
+ if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods))
+ overloadedMethods.push_back(MD);
+ }
+ }
+
+ if (foundSameNameMethod)
+ OverloadedMethods.append(overloadedMethods.begin(),
+ overloadedMethods.end());
+ return foundSameNameMethod;
+ }
+};
+} // end anonymous namespace
/// \brief Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
@@ -6363,9 +6366,9 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases.
/*bool RecordPaths=*/false,
/*bool DetectVirtual=*/false);
- FindHiddenVirtualMethodData Data;
- Data.Method = MD;
- Data.S = this;
+ FindHiddenVirtualMethod FHVM;
+ FHVM.Method = MD;
+ FHVM.S = this;
// Keep the base methods that were overriden or introduced in the subclass
// by 'using' in a set. A base method not in this set is hidden.
@@ -6376,11 +6379,11 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I))
ND = shad->getTargetDecl();
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
- AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods);
+ AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods);
}
- if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths))
- OverloadedMethods = Data.OverloadedMethods;
+ if (DC->lookupInBases(FHVM, Paths))
+ OverloadedMethods = FHVM.OverloadedMethods;
}
void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
@@ -6897,7 +6900,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
return Context.getFunctionType(Context.VoidTy, None, EPI);
}
-static void extendLeft(SourceRange &R, const SourceRange &Before) {
+static void extendLeft(SourceRange &R, SourceRange Before) {
if (Before.isInvalid())
return;
R.setBegin(Before.getBegin());
@@ -6905,7 +6908,7 @@ static void extendLeft(SourceRange &R, const SourceRange &Before) {
R.setEnd(Before.getEnd());
}
-static void extendRight(SourceRange &R, const SourceRange &After) {
+static void extendRight(SourceRange &R, SourceRange After) {
if (After.isInvalid())
return;
if (R.getBegin().isInvalid())
@@ -7019,7 +7022,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
// If we can provide a correct fix-it hint, do so.
if (After.isInvalid() && ConvTSI) {
SourceLocation InsertLoc =
- PP.getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd());
+ getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd());
DB << FixItHint::CreateInsertion(InsertLoc, " ")
<< FixItHint::CreateInsertionFromRange(
InsertLoc, CharSourceRange::getTokenRange(Before))
@@ -7102,7 +7105,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
if (ConvType == ClassType)
Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used)
<< ClassType;
- else if (IsDerivedFrom(ClassType, ConvType))
+ else if (IsDerivedFrom(Conversion->getLocation(), ClassType, ConvType))
Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used)
<< ClassType << ConvType;
} else if (ConvType->isVoidType()) {
@@ -7169,7 +7172,8 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
SourceLocation IdentLoc,
IdentifierInfo *II,
SourceLocation LBrace,
- AttributeList *AttrList) {
+ AttributeList *AttrList,
+ UsingDirectiveDecl *&UD) {
SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
// For anonymous namespace, take the location of the left brace.
SourceLocation Loc = II ? IdentLoc : LBrace;
@@ -7190,23 +7194,14 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// treated as an original-namespace-name.
//
// Since namespace names are unique in their scope, and we don't
- // look through using directives, just look for any ordinary names.
-
- const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member |
- Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag |
- Decl::IDNS_Namespace;
- NamedDecl *PrevDecl = nullptr;
- DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II);
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
- ++I) {
- if ((*I)->getIdentifierNamespace() & IDNS) {
- PrevDecl = *I;
- break;
- }
- }
-
+ // look through using directives, just look for any ordinary names
+ // as if by qualified name lookup.
+ LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration);
+ LookupQualifiedName(R, CurContext->getRedeclContext());
+ NamedDecl *PrevDecl =
+ R.isSingleResult() ? R.getRepresentativeDecl() : nullptr;
PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl);
-
+
if (PrevNS) {
// This is an extended namespace definition.
if (IsInline != PrevNS->isInline())
@@ -7293,14 +7288,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// namespace internal linkage.
if (!PrevNS) {
- UsingDirectiveDecl* UD
- = UsingDirectiveDecl::Create(Context, Parent,
- /* 'using' */ LBrace,
- /* 'namespace' */ SourceLocation(),
- /* qualifier */ NestedNameSpecifierLoc(),
- /* identifier */ SourceLocation(),
- Namespc,
- /* Ancestor */ Parent);
+ UD = UsingDirectiveDecl::Create(Context, Parent,
+ /* 'using' */ LBrace,
+ /* 'namespace' */ SourceLocation(),
+ /* qualifier */ NestedNameSpecifierLoc(),
+ /* identifier */ SourceLocation(),
+ Namespc,
+ /* Ancestor */ Parent);
UD->setImplicit();
Parent->addDecl(UD);
}
@@ -7538,7 +7532,7 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
S.PDiag(diag::err_using_directive_suggest) << Ident,
S.PDiag(diag::note_namespace_defined_here));
}
- R.addDecl(Corrected.getCorrectionDecl());
+ R.addDecl(Corrected.getFoundDecl());
return true;
}
return false;
@@ -7556,7 +7550,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
// This can only happen along a recovery path.
- while (S->getFlags() & Scope::TemplateParamScope)
+ while (S->isTemplateParamScope())
S = S->getParent();
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
@@ -7586,9 +7580,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
}
if (!R.empty()) {
- NamedDecl *Named = R.getFoundDecl();
- assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named))
- && "expected namespace decl");
+ NamedDecl *Named = R.getRepresentativeDecl();
+ NamespaceDecl *NS = R.getAsSingle<NamespaceDecl>();
+ assert(NS && "expected namespace decl");
// The use of a nested name specifier may trigger deprecation warnings.
DiagnoseUseOfDecl(Named, IdentLoc);
@@ -7605,7 +7599,6 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
// Find enclosing context containing both using-directive and
// nominated namespace.
- NamespaceDecl *NS = getNamespaceDecl(Named);
DeclContext *CommonAncestor = cast<DeclContext>(NS);
while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
CommonAncestor = CommonAncestor->getParent();
@@ -7805,7 +7798,8 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
FoundEquivalentDecl = true;
}
- (isa<TagDecl>(D) ? Tag : NonTag) = D;
+ if (isVisible(D))
+ (isa<TagDecl>(D) ? Tag : NonTag) = D;
}
if (FoundEquivalentDecl)
@@ -8014,6 +8008,10 @@ public:
// FIXME: Check that the base class member is accessible?
}
+ } else {
+ auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND);
+ if (FoundRecord && FoundRecord->isInjectedClassName())
+ return false;
}
if (isa<TypeDecl>(ND))
@@ -8377,7 +8375,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
} else {
// Convert 'using X::Y;' to 'typedef X::Y Y;'.
SourceLocation InsertLoc =
- PP.getLocForEndOfToken(NameInfo.getLocEnd());
+ getLocForEndOfToken(NameInfo.getLocEnd());
Diag(InsertLoc, diag::note_using_decl_class_member_workaround)
<< 1 // typedef declaration
<< FixItHint::CreateReplacement(UsingLoc, "typedef")
@@ -8470,40 +8468,26 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
// in the UsingDecl and UsingShadowDecl so that these checks didn't
// need to be repeated.
- struct UserData {
- llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases;
-
- static bool collect(const CXXRecordDecl *Base, void *OpaqueData) {
- UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
- Data->Bases.insert(Base);
- return true;
- }
-
- bool hasDependentBases(const CXXRecordDecl *Class) {
- return !Class->forallBases(collect, this);
- }
-
- /// Returns true if the base is dependent or is one of the
- /// accumulated base classes.
- static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) {
- UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
- return !Data->Bases.count(Base);
- }
-
- bool mightShareBases(const CXXRecordDecl *Class) {
- return Bases.count(Class) || !Class->forallBases(doesNotContain, this);
- }
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases;
+ auto Collect = [&Bases](const CXXRecordDecl *Base) {
+ Bases.insert(Base);
+ return true;
};
- UserData Data;
-
- // Returns false if we find a dependent base.
- if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext)))
+ // Collect all bases. Return false if we find a dependent base.
+ if (!cast<CXXRecordDecl>(CurContext)->forallBases(Collect))
return false;
- // Returns false if the class has a dependent base or if it or one
+ // Returns true if the base is dependent or is one of the accumulated base
+ // classes.
+ auto IsNotBase = [&Bases](const CXXRecordDecl *Base) {
+ return !Bases.count(Base);
+ };
+
+ // Return false if the class has a dependent base or if it or one
// of its bases is present in the base set of the current context.
- if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext)))
+ if (Bases.count(cast<CXXRecordDecl>(NamedContext)) ||
+ !cast<CXXRecordDecl>(NamedContext)->forallBases(IsNotBase))
return false;
Diag(SS.getRange().getBegin(),
@@ -8524,7 +8508,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
TypeResult Type,
Decl *DeclFromDeclSpec) {
// Skip up to the relevant declaration scope.
- while (S->getFlags() & Scope::TemplateParamScope)
+ while (S->isTemplateParamScope())
S = S->getParent();
assert((S->getFlags() & Scope::DeclScope) &&
"got alias-declaration outside of declaration scope");
@@ -8685,28 +8669,41 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
}
}
assert(!R.isAmbiguous() && !R.empty());
+ NamedDecl *ND = R.getRepresentativeDecl();
// Check if we have a previous declaration with the same name.
- NamedDecl *PrevDecl = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName,
- ForRedeclaration);
- if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
- PrevDecl = nullptr;
+ LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ LookupName(PrevR, S);
- NamedDecl *ND = R.getFoundDecl();
+ // Check we're not shadowing a template parameter.
+ if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) {
+ DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl());
+ PrevR.clear();
+ }
- if (PrevDecl) {
+ // Filter out any other lookup result from an enclosing scope.
+ FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false,
+ /*AllowInlineNamespace*/false);
+
+ // Find the previous declaration and check that we can redeclare it.
+ NamespaceAliasDecl *Prev = nullptr;
+ if (PrevR.isSingleResult()) {
+ NamedDecl *PrevDecl = PrevR.getRepresentativeDecl();
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
// We already have an alias with the same name that points to the same
// namespace; check that it matches.
- if (!AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
+ if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
+ Prev = AD;
+ } else if (isVisible(PrevDecl)) {
Diag(AliasLoc, diag::err_redefinition_different_namespace_alias)
<< Alias;
- Diag(PrevDecl->getLocation(), diag::note_previous_namespace_alias)
+ Diag(AD->getLocation(), diag::note_previous_namespace_alias)
<< AD->getNamespace();
return nullptr;
}
- } else {
- unsigned DiagID = isa<NamespaceDecl>(PrevDecl)
+ } else if (isVisible(PrevDecl)) {
+ unsigned DiagID = isa<NamespaceDecl>(PrevDecl->getUnderlyingDecl())
? diag::err_redefinition
: diag::err_redefinition_different_kind;
Diag(AliasLoc, DiagID) << Alias;
@@ -8722,8 +8719,8 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
Alias, SS.getWithLocInContext(Context),
IdentLoc, ND);
- if (PrevDecl)
- AliasDecl->setPreviousDecl(cast<NamespaceAliasDecl>(PrevDecl));
+ if (Prev)
+ AliasDecl->setPreviousDecl(Prev);
PushOnScopeChains(AliasDecl, S);
return AliasDecl;
@@ -9497,7 +9494,7 @@ static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
}
}
-void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) {
+void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
auto *RD = dyn_cast<CXXRecordDecl>(D);
// Default constructors that are annotated with __declspec(dllexport) which
@@ -9505,6 +9502,15 @@ void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) {
// wrapped with a thunk called the default constructor closure.
if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft())
getDefaultArgExprsForConstructors(*this, RD);
+
+ if (!DelayedDllExportClasses.empty()) {
+ // Calling ReferenceDllExportedMethods might cause the current function to
+ // be called again, so use a local copy of DelayedDllExportClasses.
+ SmallVector<CXXRecordDecl *, 4> WorkList;
+ std::swap(DelayedDllExportClasses, WorkList);
+ for (CXXRecordDecl *Class : WorkList)
+ ReferenceDllExportedMethods(*this, Class);
+ }
}
void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
@@ -9618,7 +9624,7 @@ public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(),
- nullptr, MemberLookup, nullptr).get());
+ nullptr, MemberLookup, nullptr, nullptr).get());
}
MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
@@ -9828,7 +9834,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
SS, /*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
OpLookup,
- /*TemplateArgs=*/nullptr,
+ /*TemplateArgs=*/nullptr, /*S*/nullptr,
/*SuppressQualifierCheck=*/true);
if (OpEqualRef.isInvalid())
return StmtError();
@@ -12207,7 +12213,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
diag::ext_unelaborated_friend_type)
<< (unsigned) RD->getTagKind()
<< T
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc),
+ << FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc),
InsertionText);
} else {
Diag(FriendLoc,
@@ -12673,15 +12679,30 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DC = CurContext;
assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?");
}
-
+
if (!DC->isRecord()) {
+ int DiagArg = -1;
+ switch (D.getName().getKind()) {
+ case UnqualifiedId::IK_ConstructorTemplateId:
+ case UnqualifiedId::IK_ConstructorName:
+ DiagArg = 0;
+ break;
+ case UnqualifiedId::IK_DestructorName:
+ DiagArg = 1;
+ break;
+ case UnqualifiedId::IK_ConversionFunctionId:
+ DiagArg = 2;
+ break;
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_ImplicitSelfParam:
+ case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedId::IK_TemplateId:
+ break;
+ }
// This implies that it has to be an operator or function.
- if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
- D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
- D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
- Diag(Loc, diag::err_introducing_special_friend) <<
- (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
- D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
+ if (DiagArg >= 0) {
+ Diag(Loc, diag::err_introducing_special_friend) << DiagArg;
return nullptr;
}
}
@@ -12983,7 +13004,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
// Check if the new class derives from the old class.
- if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
+ if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) {
Diag(New->getLocation(), diag::err_covariant_return_not_derived)
<< New->getDeclName() << NewTy << OldTy
<< New->getReturnTypeSourceRange();
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index f42c4b7546ce..a2f41a7cc30a 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -15,12 +15,11 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
-#include "clang/AST/DataRecursiveASTVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Lookup.h"
@@ -100,9 +99,8 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
// If we're in a system header, and this is not a call, just make
// the method unusable.
if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) {
- method->addAttr(UnavailableAttr::CreateImplicit(Context,
- "init method returns a type unrelated to its receiver type",
- loc));
+ method->addAttr(UnavailableAttr::CreateImplicit(Context, "",
+ UnavailableAttr::IR_ARCInitReturnsUnrelated, loc));
return true;
}
@@ -449,7 +447,7 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
ObjCInterfaceDecl *CurrentIDecl;
};
-}
+} // end anonymous namespace
static void diagnoseUseOfProtocols(Sema &TheSema,
ObjCContainerDecl *CD,
@@ -484,7 +482,7 @@ ActOnSuperClassOfClassInterface(Scope *S,
if (TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(SuperName, SuperLoc),
LookupOrdinaryName, TUScope,
- NULL, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
+ nullptr, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
CTK_ErrorRecovery)) {
diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
<< SuperName << ClassName);
@@ -507,7 +505,7 @@ ActOnSuperClassOfClassInterface(Scope *S,
SuperClassType = Context.getObjCInterfaceType(SuperClassDecl);
}
- if (PrevDecl && SuperClassDecl == 0) {
+ if (PrevDecl && !SuperClassDecl) {
// The previous declaration was not a class decl. Check if we have a
// typedef. If we do, get the underlying class type.
if (const TypedefNameDecl *TDecl =
@@ -548,7 +546,7 @@ ActOnSuperClassOfClassInterface(Scope *S,
SuperClassDecl->getDeclName(),
ClassName,
SourceRange(AtInterfaceLoc, ClassLoc))) {
- SuperClassDecl = 0;
+ SuperClassDecl = nullptr;
SuperClassType = QualType();
}
}
@@ -608,7 +606,7 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S,
} else if (typeBound->isObjCObjectType()) {
// The user forgot the * on an Objective-C pointer type, e.g.,
// "T : NSView".
- SourceLocation starLoc = PP.getLocForEndOfToken(
+ SourceLocation starLoc = getLocForEndOfToken(
typeBoundInfo->getTypeLoc().getEndLoc());
Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
diag::err_objc_type_param_bound_missing_pointer)
@@ -638,20 +636,44 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S,
typeBoundInfo = nullptr;
}
- // Type bounds cannot have explicit nullability.
+ // Type bounds cannot have qualifiers (even indirectly) or explicit
+ // nullability.
if (typeBoundInfo) {
- // Type arguments cannot explicitly specify nullability.
- if (auto nullability = AttributedType::stripOuterNullability(typeBound)) {
- // Look at the type location information to find the nullability
- // specifier so we can zap it.
- SourceLocation nullabilityLoc
- = typeBoundInfo->getTypeLoc().findNullabilityLoc();
- SourceLocation diagLoc
- = nullabilityLoc.isValid()? nullabilityLoc
- : typeBoundInfo->getTypeLoc().getLocStart();
- Diag(diagLoc, diag::err_type_param_bound_explicit_nullability)
- << paramName << typeBoundInfo->getType()
- << FixItHint::CreateRemoval(nullabilityLoc);
+ QualType typeBound = typeBoundInfo->getType();
+ TypeLoc qual = typeBoundInfo->getTypeLoc().findExplicitQualifierLoc();
+ if (qual || typeBound.hasQualifiers()) {
+ bool diagnosed = false;
+ SourceRange rangeToRemove;
+ if (qual) {
+ if (auto attr = qual.getAs<AttributedTypeLoc>()) {
+ rangeToRemove = attr.getLocalSourceRange();
+ if (attr.getTypePtr()->getImmediateNullability()) {
+ Diag(attr.getLocStart(),
+ diag::err_objc_type_param_bound_explicit_nullability)
+ << paramName << typeBound
+ << FixItHint::CreateRemoval(rangeToRemove);
+ diagnosed = true;
+ }
+ }
+ }
+
+ if (!diagnosed) {
+ Diag(qual ? qual.getLocStart()
+ : typeBoundInfo->getTypeLoc().getLocStart(),
+ diag::err_objc_type_param_bound_qualified)
+ << paramName << typeBound << typeBound.getQualifiers().getAsString()
+ << FixItHint::CreateRemoval(rangeToRemove);
+ }
+
+ // If the type bound has qualifiers other than CVR, we need to strip
+ // them or we'll probably assert later when trying to apply new
+ // qualifiers.
+ Qualifiers quals = typeBound.getQualifiers();
+ quals.removeCVRQualifiers();
+ if (!quals.empty()) {
+ typeBoundInfo =
+ Context.getTrivialTypeSourceInfo(typeBound.getUnqualifiedType());
+ }
}
}
}
@@ -722,7 +744,7 @@ namespace {
Category,
Extension
};
-}
+} // end anonymous namespace
/// Check consistency between two Objective-C type parameter lists, e.g.,
/// between a category/extension and an \@interface or between an \@class and an
@@ -737,7 +759,7 @@ static bool checkTypeParamListConsistency(Sema &S,
if (newTypeParams->size() > prevTypeParams->size()) {
diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation();
} else {
- diagLoc = S.PP.getLocForEndOfToken(newTypeParams->back()->getLocEnd());
+ diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getLocEnd());
}
S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch)
@@ -852,7 +874,7 @@ static bool checkTypeParamListConsistency(Sema &S,
newContext == TypeParamListContext::Definition) {
// Diagnose this problem for forward declarations and definitions.
SourceLocation insertionLoc
- = S.PP.getLocForEndOfToken(newTypeParam->getLocation());
+ = S.getLocForEndOfToken(newTypeParam->getLocation());
std::string newCode
= " : " + prevTypeParam->getUnderlyingType().getAsString(
S.Context.getPrintingPolicy());
@@ -1184,26 +1206,23 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,
/// protocol declarations in its 'Protocols' argument.
void
Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
- const IdentifierLocPair *ProtocolId,
- unsigned NumProtocols,
+ ArrayRef<IdentifierLocPair> ProtocolId,
SmallVectorImpl<Decl *> &Protocols) {
- for (unsigned i = 0; i != NumProtocols; ++i) {
- ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
- ProtocolId[i].second);
+ for (const IdentifierLocPair &Pair : ProtocolId) {
+ ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second);
if (!PDecl) {
TypoCorrection Corrected = CorrectTypo(
- DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
+ DeclarationNameInfo(Pair.first, Pair.second),
LookupObjCProtocolName, TUScope, nullptr,
llvm::make_unique<DeclFilterCCC<ObjCProtocolDecl>>(),
CTK_ErrorRecovery);
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest)
- << ProtocolId[i].first);
+ << Pair.first);
}
if (!PDecl) {
- Diag(ProtocolId[i].second, diag::err_undeclared_protocol)
- << ProtocolId[i].first;
+ Diag(Pair.second, diag::err_undeclared_protocol) << Pair.first;
continue;
}
// If this is a forward protocol declaration, get its definition.
@@ -1213,7 +1232,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
// For an objc container, delay protocol reference checking until after we
// can set the objc decl as the availability context, otherwise check now.
if (!ForObjCContainer) {
- (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
+ (void)DiagnoseUseOfDecl(PDecl, Pair.second);
}
// If this is a forward declaration and we are supposed to warn in this
@@ -1223,8 +1242,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
if (WarnOnDeclarations &&
NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) {
- Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
- << ProtocolId[i].first;
+ Diag(Pair.second, diag::warn_undef_protocolref) << Pair.first;
Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined)
<< UndefinedProtocol;
}
@@ -1388,8 +1406,8 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
if (allProtocolsDeclared) {
Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type)
<< baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc)
- << FixItHint::CreateInsertion(
- PP.getLocForEndOfToken(firstClassNameLoc), " *");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(firstClassNameLoc),
+ " *");
}
}
@@ -1469,15 +1487,15 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
// If we have a typedef of an Objective-C class type that is missing a '*',
// add the '*'.
if (type->getAs<ObjCInterfaceType>()) {
- SourceLocation starLoc = PP.getLocForEndOfToken(loc);
+ SourceLocation starLoc = getLocForEndOfToken(loc);
ParsedAttributes parsedAttrs(attrFactory);
D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc,
SourceLocation(),
SourceLocation(),
SourceLocation(),
SourceLocation()),
- parsedAttrs,
- starLoc);
+ parsedAttrs,
+ starLoc);
// Diagnose the missing '*'.
Diag(loc, diag::err_objc_type_arg_missing_star)
@@ -1655,17 +1673,16 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
/// ActOnForwardProtocolDeclaration - Handle \@protocol foo;
Sema::DeclGroupPtrTy
Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
- const IdentifierLocPair *IdentList,
- unsigned NumElts,
+ ArrayRef<IdentifierLocPair> IdentList,
AttributeList *attrList) {
SmallVector<Decl *, 8> DeclsInGroup;
- for (unsigned i = 0; i != NumElts; ++i) {
- IdentifierInfo *Ident = IdentList[i].first;
- ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentList[i].second,
+ for (const IdentifierLocPair &IdentPair : IdentList) {
+ IdentifierInfo *Ident = IdentPair.first;
+ ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentPair.second,
ForRedeclaration);
ObjCProtocolDecl *PDecl
= ObjCProtocolDecl::Create(Context, CurContext, Ident,
- IdentList[i].second, AtProtocolLoc,
+ IdentPair.second, AtProtocolLoc,
PrevDecl);
PushOnScopeChains(PDecl, TUScope);
@@ -1850,6 +1867,8 @@ Decl *Sema::ActOnStartClassImplementation(
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
} else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
+ // FIXME: This will produce an error if the definition of the interface has
+ // been imported from a module but is not visible.
RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
diag::warn_undef_interface);
} else {
@@ -2247,7 +2266,7 @@ static bool CheckMethodOverrideReturn(Sema &S,
DiagID =
IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types
- : diag::warn_non_covariant_ret_types;
+ : diag::warn_non_covariant_ret_types;
}
}
@@ -2331,7 +2350,7 @@ static bool CheckMethodOverrideParam(Sema &S,
DiagID =
IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types
- : diag::warn_non_contravariant_param_types;
+ : diag::warn_non_contravariant_param_types;
}
}
@@ -2340,7 +2359,7 @@ static bool CheckMethodOverrideParam(Sema &S,
<< MethodImpl->getDeclName() << IfaceTy << ImplTy;
S.Diag(IfaceVar->getLocation(),
(IsOverridingMode ? diag::note_previous_declaration
- : diag::note_previous_definition))
+ : diag::note_previous_definition))
<< getTypeRange(IfaceVar->getTypeSourceInfo());
return false;
}
@@ -2749,7 +2768,8 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
if (!WarnCategoryMethodImpl) {
for (auto *Cat : I->visible_categories())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl, Cat, IncompleteImpl, false,
+ IMPDecl, Cat, IncompleteImpl,
+ ImmediateClass && Cat->IsClassExtension(),
WarnCategoryMethodImpl);
} else {
// Also methods in class extensions need be looked at next.
@@ -2825,6 +2845,20 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
for (const auto *I : IMPDecl->instance_methods())
InsMap.insert(I->getSelector());
+ // Add the selectors for getters/setters of @dynamic properties.
+ for (const auto *PImpl : IMPDecl->property_impls()) {
+ // We only care about @dynamic implementations.
+ if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic)
+ continue;
+
+ const auto *P = PImpl->getPropertyDecl();
+ if (!P) continue;
+
+ InsMap.insert(P->getGetterName());
+ if (!P->getSetterName().isNull())
+ InsMap.insert(P->getSetterName());
+ }
+
// Check and see if properties declared in the interface have either 1)
// an implementation or 2) there is a @synthesize/@dynamic implementation
// of the property in the @implementation.
@@ -2866,9 +2900,6 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
for (auto *PI : I->all_referenced_protocols())
CheckProtocolMethodDefs(*this, IMPDecl->getLocation(), PI, IncompleteImpl,
InsMap, ClsMap, I, ExplicitImplProtocols);
- // Check class extensions (unnamed categories)
- for (auto *Ext : I->visible_extensions())
- ImplMethodsVsClassMethods(S, IMPDecl, Ext, IncompleteImpl);
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
// For extended class, unimplemented methods in its protocols will
// be reported in the primary class.
@@ -3478,6 +3509,23 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
}
}
+/// Diagnose attempts to define ARC-__weak ivars when __weak is disabled.
+static void DiagnoseWeakIvars(Sema &S, ObjCImplementationDecl *ID) {
+ if (S.getLangOpts().ObjCWeak) return;
+
+ for (auto ivar = ID->getClassInterface()->all_declared_ivar_begin();
+ ivar; ivar = ivar->getNextIvar()) {
+ if (ivar->isInvalidDecl()) continue;
+ if (ivar->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
+ if (S.getLangOpts().ObjCWeakRuntime) {
+ S.Diag(ivar->getLocation(), diag::err_arc_weak_disabled);
+ } else {
+ S.Diag(ivar->getLocation(), diag::err_arc_weak_no_runtime);
+ }
+ }
+ }
+}
+
Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
switch (CurContext->getDeclKind()) {
case Decl::ObjCInterface:
@@ -3590,7 +3638,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
// user-defined setter/getter. It also synthesizes setter/getter methods
// and adds them to the DeclContext and global method pools.
for (auto *I : CDecl->properties())
- ProcessPropertyDecl(I, CDecl);
+ ProcessPropertyDecl(I);
CDecl->setAtEndRange(AtEnd);
}
if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
@@ -3627,6 +3675,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
DiagnoseUnusedBackingIvarInAccessor(S, IC);
if (IDecl->hasDesignatedInitializers())
DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
+ DiagnoseWeakIvars(*this, IC);
bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
if (IDecl->getSuperClass() == nullptr) {
@@ -3700,7 +3749,6 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
return ClassDecl;
}
-
/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for
/// objective-c's type qualifier from the parser version of the same info.
static Decl::ObjCDeclQualifier
@@ -3867,7 +3915,6 @@ private:
search(Interface);
}
-
void search(const ObjCProtocolList &protocols) {
for (ObjCProtocolList::iterator i = protocols.begin(), e = protocols.end();
i != e; ++i)
@@ -3895,7 +3942,7 @@ private:
searchFromContainer(container);
}
};
-}
+} // end anonymous namespace
void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
ObjCInterfaceDecl *CurrentClass,
@@ -4490,7 +4537,6 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
if (!LookupImplementedMethodInGlobalPool(Sel))
Diag(Loc, diag::warn_unimplemented_selector) << Sel;
}
- return;
}
ObjCIvarDecl *
@@ -4522,7 +4568,7 @@ namespace {
/// Used by Sema::DiagnoseUnusedBackingIvarInAccessor to check if a property
/// accessor references the backing ivar.
class UnusedBackingIvarChecker :
- public DataRecursiveASTVisitor<UnusedBackingIvarChecker> {
+ public RecursiveASTVisitor<UnusedBackingIvarChecker> {
public:
Sema &S;
const ObjCMethodDecl *Method;
@@ -4553,7 +4599,7 @@ namespace {
return true;
}
};
-}
+} // end anonymous namespace
void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S,
const ObjCImplementationDecl *ImplD) {
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 2cf02b484cb4..f12bf2415dba 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -68,7 +68,7 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
///
/// \param[in,out] T The exception type. This will be decayed to a pointer type
/// when the input is an array or a function type.
-bool Sema::CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range) {
+bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
// C++11 [except.spec]p2:
// A type cv T, "array of T", or "function returning T" denoted
// in an exception-specification is adjusted to type T, "pointer to T", or
@@ -232,7 +232,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) {
Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch)
<< hasImplicitExceptionSpec(Old);
- if (!Old->getLocation().isInvalid())
+ if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_declaration);
}
return false;
@@ -270,16 +270,35 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType();
if (ESI.Type == EST_Dynamic) {
ESI.Exceptions = OldProto->exceptions();
- } else if (ESI.Type == EST_ComputedNoexcept) {
- // FIXME: We can't just take the expression from the old prototype. It
- // likely contains references to the old prototype's parameters.
}
- // Update the type of the function with the appropriate exception
- // specification.
- New->setType(Context.getFunctionType(
- NewProto->getReturnType(), NewProto->getParamTypes(),
- NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
+ if (ESI.Type == EST_ComputedNoexcept) {
+ // For computed noexcept, we can't just take the expression from the old
+ // prototype. It likely contains references to the old prototype's
+ // parameters.
+ New->setInvalidDecl();
+ } else {
+ // Update the type of the function with the appropriate exception
+ // specification.
+ New->setType(Context.getFunctionType(
+ NewProto->getReturnType(), NewProto->getParamTypes(),
+ NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
+ }
+
+ if (getLangOpts().MicrosoftExt && ESI.Type != EST_ComputedNoexcept) {
+ // Allow missing exception specifications in redeclarations as an extension.
+ DiagID = diag::ext_ms_missing_exception_specification;
+ ReturnValueOnError = false;
+ } else if (New->isReplaceableGlobalAllocationFunction() &&
+ ESI.Type != EST_ComputedNoexcept) {
+ // Allow missing exception specifications in redeclarations as an extension,
+ // when declaring a replaceable global allocation function.
+ DiagID = diag::ext_missing_exception_specification;
+ ReturnValueOnError = false;
+ } else {
+ DiagID = diag::err_missing_exception_specification;
+ ReturnValueOnError = true;
+ }
// Warn about the lack of exception specification.
SmallString<128> ExceptionSpecString;
@@ -318,30 +337,30 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
default:
llvm_unreachable("This spec type is compatible with none.");
}
- OS.flush();
SourceLocation FixItLoc;
if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
- if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
- FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd());
+ // FIXME: Preserve enough information so that we can produce a correct fixit
+ // location when there is a trailing return type.
+ if (auto FTLoc = TL.getAs<FunctionProtoTypeLoc>())
+ if (!FTLoc.getTypePtr()->hasTrailingReturn())
+ FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd());
}
if (FixItLoc.isInvalid())
- Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ Diag(New->getLocation(), DiagID)
<< New << OS.str();
else {
- // FIXME: This will get more complicated with C++0x
- // late-specified return types.
- Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ Diag(New->getLocation(), DiagID)
<< New << OS.str()
<< FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
}
- if (!Old->getLocation().isInvalid())
+ if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_declaration);
- return false;
+ return ReturnValueOnError;
}
/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
@@ -694,7 +713,7 @@ bool Sema::CheckExceptionSpecSubset(
continue;
Paths.clear();
- if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths))
+ if (!IsDerivedFrom(SubLoc, CanonicalSubT, CanonicalSuperT, Paths))
continue;
if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT)))
@@ -979,8 +998,9 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::LambdaExprClass: {
const LambdaExpr *Lambda = cast<LambdaExpr>(E);
CanThrowResult CT = CT_Cannot;
- for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
- CapEnd = Lambda->capture_init_end();
+ for (LambdaExpr::const_capture_init_iterator
+ Cap = Lambda->capture_init_begin(),
+ CapEnd = Lambda->capture_init_end();
Cap != CapEnd; ++Cap)
CT = mergeCanThrow(CT, canThrow(*Cap));
return CT;
@@ -1043,8 +1063,10 @@ CanThrowResult Sema::canThrow(const Expr *E) {
// Many other things have subexpressions, so we have to test those.
// Some are simple:
+ case Expr::CoawaitExprClass:
case Expr::ConditionalOperatorClass:
case Expr::CompoundLiteralExprClass:
+ case Expr::CoyieldExprClass:
case Expr::CXXConstCastExprClass:
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXStdInitializerListExprClass:
@@ -1065,6 +1087,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
// Some might be dependent for other reasons.
case Expr::ArraySubscriptExprClass:
+ case Expr::OMPArraySectionExprClass:
case Expr::BinaryOperatorClass:
case Expr::CompoundAssignOperatorClass:
case Expr::CStyleCastExprClass:
@@ -1156,6 +1179,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
return CT_Cannot;
case Expr::MSPropertyRefExprClass:
+ case Expr::MSPropertySubscriptExprClass:
llvm_unreachable("Invalid class for expression");
#define STMT(CLASS, PARENT) case Expr::CLASS##Class:
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 6499cb5d19eb..5d0c6057f54f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
@@ -326,18 +327,16 @@ 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.
- SuppressedDiagnosticsMap::iterator
- Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
+ auto Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
if (Pos != SuppressedDiagnostics.end()) {
- SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
- for (unsigned I = 0, N = Suppressed.size(); I != N; ++I)
- Diag(Suppressed[I].first, Suppressed[I].second);
+ for (const PartialDiagnosticAt &Suppressed : Pos->second)
+ Diag(Suppressed.first, Suppressed.second);
// Clear out the list of suppressed diagnostics, so that we don't emit
// them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
// diagnostics again.
- Suppressed.clear();
+ Pos->second.clear();
}
// C++ [basic.start.main]p3:
@@ -348,8 +347,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D)) {
+ const AutoType *AT = cast<VarDecl>(D)->getType()->getContainedAutoType();
+
Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
- << D->getDeclName();
+ << D->getDeclName() << (unsigned)AT->getKeyword();
return true;
}
@@ -464,7 +465,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
// 'nil' for ObjC methods, where it's much more likely that the
// variadic arguments form a list of object pointers.
SourceLocation MissingNilLoc
- = PP.getLocForEndOfToken(sentinelExpr->getLocEnd());
+ = getLocForEndOfToken(sentinelExpr->getLocEnd());
std::string NullValue;
if (calleeType == CT_Method && PP.isMacroDefined("nil"))
NullValue = "nil";
@@ -493,7 +494,7 @@ SourceRange Sema::getExprRange(Expr *E) const {
//===----------------------------------------------------------------------===//
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
-ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
+ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
@@ -508,9 +509,16 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
// If we are here, we are not calling a function but taking
// its address (which is not allowed in OpenCL v1.0 s6.8.a.3).
if (getLangOpts().OpenCL) {
- Diag(E->getExprLoc(), diag::err_opencl_taking_function_address);
+ if (Diagnose)
+ Diag(E->getExprLoc(), diag::err_opencl_taking_function_address);
return ExprError();
}
+
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+ if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
+ if (!checkAddressOfFunctionIsAvailable(FD, Diagnose, E->getExprLoc()))
+ return ExprError();
+
E = ImpCastExprToType(E, Context.getPointerType(Ty),
CK_FunctionToPointerDecay).get();
} else if (Ty->isArrayType()) {
@@ -579,7 +587,7 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
&S.Context.Idents.get("object_setClass"),
SourceLocation(), S.LookupOrdinaryName);
if (ObjectSetClass) {
- SourceLocation RHSLocEnd = S.PP.getLocForEndOfToken(RHS->getLocEnd());
+ SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getLocEnd());
S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign) <<
FixItHint::CreateInsertion(OIRE->getLocStart(), "object_setClass(") <<
FixItHint::CreateReplacement(SourceRange(OIRE->getOpLoc(),
@@ -676,6 +684,11 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (T.hasQualifiers())
T = T.getUnqualifiedType();
+ // Under the MS ABI, lock down the inheritance model now.
+ if (T->isMemberPointerType() &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft())
+ (void)isCompleteType(E->getExprLoc(), T);
+
UpdateMarkingForLValueToRValue(E);
// Loading a __weak object implicitly retains the value, so we need a cleanup to
@@ -699,8 +712,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
return Res;
}
-ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) {
- ExprResult Res = DefaultFunctionArrayConversion(E);
+ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose) {
+ ExprResult Res = DefaultFunctionArrayConversion(E, Diagnose);
if (Res.isInvalid())
return ExprError();
Res = DefaultLvalueConversion(Res.get());
@@ -1349,11 +1362,13 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
ArrayRef<Expr *> Exprs) {
unsigned NumAssocs = Types.size();
assert(NumAssocs == Exprs.size());
- if (ControllingExpr->getType()->isPlaceholderType()) {
- ExprResult result = CheckPlaceholderExpr(ControllingExpr);
- if (result.isInvalid()) return ExprError();
- ControllingExpr = result.get();
- }
+
+ // Decay and strip qualifiers for the controlling expression type, and handle
+ // placeholder type replacement. See committee discussion from WG14 DR423.
+ ExprResult R = DefaultFunctionArrayLvalueConversion(ControllingExpr);
+ if (R.isInvalid())
+ return ExprError();
+ ControllingExpr = R.get();
// The controlling expression is an unevaluated operand, so side effects are
// likely unintended.
@@ -1445,12 +1460,11 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match)
<< ControllingExpr->getSourceRange() << ControllingExpr->getType()
<< (unsigned) CompatIndices.size();
- for (SmallVectorImpl<unsigned>::iterator I = CompatIndices.begin(),
- E = CompatIndices.end(); I != E; ++I) {
- Diag(Types[*I]->getTypeLoc().getBeginLoc(),
+ for (unsigned I : CompatIndices) {
+ Diag(Types[I]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
- << Types[*I]->getTypeLoc().getSourceRange()
- << Types[*I]->getType();
+ << Types[I]->getTypeLoc().getSourceRange()
+ << Types[I]->getType();
}
return ExprError();
}
@@ -1533,8 +1547,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
return ExprError();
SmallVector<SourceLocation, 4> StringTokLocs;
- for (unsigned i = 0; i != StringToks.size(); ++i)
- StringTokLocs.push_back(StringToks[i].getLocation());
+ for (const Token &Tok : StringToks)
+ StringTokLocs.push_back(Tok.getLocation());
QualType CharTy = Context.CharTy;
StringLiteral::StringKind Kind = StringLiteral::Ascii;
@@ -1697,7 +1711,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
MarkDeclRefReferenced(E);
- if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) &&
+ if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
Ty.getObjCLifetime() == Qualifiers::OCL_Weak &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
recordUseOfEvaluatedWeak(E);
@@ -1762,10 +1776,9 @@ static void emitEmptyLookupTypoDiagnostic(
std::string CorrectedStr = TC.getAsString(SemaRef.getLangOpts());
bool DroppedSpecifier =
TC.WillReplaceSpecifier() && Typo.getAsString() == CorrectedStr;
- unsigned NoteID =
- (TC.getCorrectionDecl() && isa<ImplicitParamDecl>(TC.getCorrectionDecl()))
- ? diag::note_implicit_param_decl
- : diag::note_previous_decl;
+ unsigned NoteID = TC.getCorrectionDeclAs<ImplicitParamDecl>()
+ ? diag::note_implicit_param_decl
+ : diag::note_previous_decl;
if (!Ctx)
SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo,
SemaRef.PDiag(NoteID));
@@ -1799,8 +1812,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// unqualified lookup. This is useful when (for example) the
// original lookup would not have found something because it was a
// dependent name.
- DeclContext *DC = (SS.isEmpty() && !CallsUndergoingInstantiation.empty())
- ? CurContext : nullptr;
+ DeclContext *DC = SS.isEmpty() ? CurContext : nullptr;
while (DC) {
if (isa<CXXRecordDecl>(DC)) {
LookupQualifiedName(R, DC);
@@ -1819,7 +1831,6 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
bool isInstance = CurMethod &&
CurMethod->isInstance() &&
DC == CurMethod->getParent() && !isDefaultArgument;
-
// Give a code modification hint to insert 'this->'.
// TODO: fixit for inserting 'Base<T>::' in the other cases.
@@ -1829,46 +1840,14 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
if (isInstance) {
Diag(R.getNameLoc(), diagnostic) << Name
<< FixItHint::CreateInsertion(R.getNameLoc(), "this->");
- UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(
- CallsUndergoingInstantiation.back()->getCallee());
-
- CXXMethodDecl *DepMethod;
- if (CurMethod->isDependentContext())
- DepMethod = CurMethod;
- else if (CurMethod->getTemplatedKind() ==
- FunctionDecl::TK_FunctionTemplateSpecialization)
- DepMethod = cast<CXXMethodDecl>(CurMethod->getPrimaryTemplate()->
- getInstantiatedFromMemberTemplate()->getTemplatedDecl());
- else
- DepMethod = cast<CXXMethodDecl>(
- CurMethod->getInstantiatedFromMemberFunction());
- assert(DepMethod && "No template pattern found");
-
- QualType DepThisType = DepMethod->getThisType(Context);
CheckCXXThisCapture(R.getNameLoc());
- CXXThisExpr *DepThis = new (Context) CXXThisExpr(
- R.getNameLoc(), DepThisType, false);
- TemplateArgumentListInfo TList;
- if (ULE->hasExplicitTemplateArgs())
- ULE->copyTemplateArgumentsInto(TList);
-
- CXXScopeSpec SS;
- SS.Adopt(ULE->getQualifierLoc());
- CXXDependentScopeMemberExpr *DepExpr =
- CXXDependentScopeMemberExpr::Create(
- Context, DepThis, DepThisType, true, SourceLocation(),
- SS.getWithLocInContext(Context),
- ULE->getTemplateKeywordLoc(), nullptr,
- R.getLookupNameInfo(),
- ULE->hasExplicitTemplateArgs() ? &TList : nullptr);
- CallsUndergoingInstantiation.back()->setCallee(DepExpr);
} else {
Diag(R.getNameLoc(), diagnostic) << Name;
}
// Do we really want to note all of these?
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
- Diag((*I)->getLocation(), diag::note_dependent_var_use);
+ for (NamedDecl *D : R)
+ Diag(D->getLocation(), diag::note_dependent_var_use);
// Return true if we are inside a default argument instantiation
// and the found name refers to an instance member function, otherwise
@@ -1923,28 +1902,26 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
bool AcceptableWithRecovery = false;
bool AcceptableWithoutRecovery = false;
- NamedDecl *ND = Corrected.getCorrectionDecl();
+ NamedDecl *ND = Corrected.getFoundDecl();
if (ND) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(R.getNameLoc(),
OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
- for (TypoCorrection::decl_iterator CD = Corrected.begin(),
- CDEnd = Corrected.end();
- CD != CDEnd; ++CD) {
+ for (NamedDecl *CD : Corrected) {
if (FunctionTemplateDecl *FTD =
- dyn_cast<FunctionTemplateDecl>(*CD))
+ dyn_cast<FunctionTemplateDecl>(CD))
AddTemplateOverloadCandidate(
FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs,
Args, OCS);
- else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+ else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD))
if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0)
AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none),
Args, OCS);
}
switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
case OR_Success:
- ND = Best->Function;
+ ND = Best->FoundDecl;
Corrected.setCorrectionDecl(ND);
break;
default:
@@ -1966,15 +1943,16 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
R.setNamingClass(Record);
}
- AcceptableWithRecovery =
- isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND);
+ auto *UnderlyingND = ND->getUnderlyingDecl();
+ AcceptableWithRecovery = isa<ValueDecl>(UnderlyingND) ||
+ isa<FunctionTemplateDecl>(UnderlyingND);
// FIXME: If we ended up with a typo for a type name or
// Objective-C class name, we're in trouble because the parser
// is in the wrong place to recover. Suggest the typo
// correction, but don't make it a fix-it since we're not going
// to recover well anyway.
AcceptableWithoutRecovery =
- isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
+ isa<TypeDecl>(UnderlyingND) || isa<ObjCInterfaceDecl>(UnderlyingND);
} else {
// FIXME: We found a keyword. Suggest it, but don't provide a fix-it
// because we aren't able to recover.
@@ -1982,8 +1960,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
}
if (AcceptableWithRecovery || AcceptableWithoutRecovery) {
- unsigned NoteID = (Corrected.getCorrectionDecl() &&
- isa<ImplicitParamDecl>(Corrected.getCorrectionDecl()))
+ unsigned NoteID = Corrected.getCorrectionDeclAs<ImplicitParamDecl>()
? diag::note_implicit_param_decl
: diag::note_previous_decl;
if (SS.isEmpty())
@@ -2278,7 +2255,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
- R, TemplateArgs);
+ R, TemplateArgs, S);
}
if (TemplateArgs || TemplateKWLoc.isValid()) {
@@ -2302,11 +2279,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
/// declaration name, generally during template instantiation.
/// There's a large number of things which don't need to be done along
/// this path.
-ExprResult
-Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- bool IsAddressOfOperand,
- TypeSourceInfo **RecoveryTSI) {
+ExprResult Sema::BuildQualifiedDeclarationNameExpr(
+ CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo,
+ bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) {
DeclContext *DC = computeDeclContext(SS, false);
if (!DC)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
@@ -2373,7 +2348,7 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand)
return BuildPossibleImplicitMemberExpr(SS,
/*TemplateKWLoc=*/SourceLocation(),
- R, /*TemplateArgs=*/nullptr);
+ R, /*TemplateArgs=*/nullptr, S);
return BuildDeclarationNameExpr(SS, R, /* ADL */ false);
}
@@ -2615,7 +2590,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
// In C++98, the qualifier type doesn't actually have to be a base
// type of the object type, in which case we just ignore it.
// Otherwise build the appropriate casts.
- if (IsDerivedFrom(FromRecordType, QRecordType)) {
+ if (IsDerivedFrom(FromLoc, FromRecordType, QRecordType)) {
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
FromLoc, FromRange, &BasePath))
@@ -2651,7 +2626,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
// We only need to do this if the naming-class to declaring-class
// conversion is non-trivial.
if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
- assert(IsDerivedFrom(FromRecordType, URecordType));
+ assert(IsDerivedFrom(FromLoc, FromRecordType, URecordType));
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
FromLoc, FromRange, &BasePath))
@@ -2698,9 +2673,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
// Turn off ADL when we find certain kinds of declarations during
// normal lookup:
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- NamedDecl *D = *I;
-
+ for (NamedDecl *D : R) {
// C++0x [basic.lookup.argdep]p3:
// -- a declaration of a class member
// Since using decls preserve this property, we check this on the
@@ -3355,13 +3328,6 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Get the value in the widest-possible width.
unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth();
- // The microsoft literal suffix extensions support 128-bit literals, which
- // may be wider than [u]intmax_t.
- // FIXME: Actually, they don't. We seem to have accidentally invented the
- // i128 suffix.
- if (Literal.MicrosoftInteger == 128 && MaxWidth < 128 &&
- Context.getTargetInfo().hasInt128Type())
- MaxWidth = 128;
llvm::APInt ResultVal(MaxWidth, 0);
if (Literal.GetIntegerValue(ResultVal)) {
@@ -3384,12 +3350,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Microsoft specific integer suffixes are explicitly sized.
if (Literal.MicrosoftInteger) {
- if (Literal.MicrosoftInteger > MaxWidth) {
- // If this target doesn't support __int128, error and force to ull.
- Diag(Tok.getLocation(), diag::err_int128_unsupported);
- Width = MaxWidth;
- Ty = Context.getIntMaxType();
- } else if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) {
+ if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) {
Width = 8;
Ty = Context.CharTy;
} else {
@@ -3726,7 +3687,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) {
return false;
if (E->getObjectKind() == OK_BitField) {
- S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield)
+ S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield)
<< 1 << E->getSourceRange();
return true;
}
@@ -3828,7 +3789,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
isInvalid = true;
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
- Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 0;
isInvalid = true;
} else {
isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf);
@@ -3854,7 +3815,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
ExprResult
Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind, bool IsType,
- void *TyOrEx, const SourceRange &ArgRange) {
+ void *TyOrEx, SourceRange ArgRange) {
// If error parsing type, ignore.
if (!TyOrEx) return ExprError();
@@ -3940,9 +3901,21 @@ static bool checkArithmeticOnObjCPointer(Sema &S,
return true;
}
+static bool isMSPropertySubscriptExpr(Sema &S, Expr *Base) {
+ auto *BaseNoParens = Base->IgnoreParens();
+ if (auto *MSProp = dyn_cast<MSPropertyRefExpr>(BaseNoParens))
+ return MSProp->getPropertyDecl()->getType()->isArrayType();
+ return isa<MSPropertySubscriptExpr>(BaseNoParens);
+}
+
ExprResult
Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
Expr *idx, SourceLocation rbLoc) {
+ if (base && !base->getType().isNull() &&
+ base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection))
+ return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(),
+ /*Length=*/nullptr, rbLoc);
+
// Since this might be a postfix expression, get rid of ParenListExprs.
if (isa<ParenListExpr>(base)) {
ExprResult result = MaybeConvertParenListExprToParenExpr(S, base);
@@ -3955,10 +3928,15 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
// operand might be an overloadable type, in which case the overload
// resolution for the operator overload should get the first crack
// at the overload.
+ bool IsMSPropertySubscript = false;
if (base->getType()->isNonOverloadPlaceholderType()) {
- ExprResult result = CheckPlaceholderExpr(base);
- if (result.isInvalid()) return ExprError();
- base = result.get();
+ IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base);
+ if (!IsMSPropertySubscript) {
+ ExprResult result = CheckPlaceholderExpr(base);
+ if (result.isInvalid())
+ return ExprError();
+ base = result.get();
+ }
}
if (idx->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(idx);
@@ -3973,6 +3951,21 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
VK_LValue, OK_Ordinary, rbLoc);
}
+ // MSDN, property (C++)
+ // https://msdn.microsoft.com/en-us/library/yhfk0thd(v=vs.120).aspx
+ // This attribute can also be used in the declaration of an empty array in a
+ // class or structure definition. For example:
+ // __declspec(property(get=GetX, put=PutX)) int x[];
+ // The above statement indicates that x[] can be used with one or more array
+ // indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b),
+ // and p->x[a][b] = i will be turned into p->PutX(a, b, i);
+ if (IsMSPropertySubscript) {
+ // Build MS property subscript expression if base is MS property reference
+ // or MS property subscript.
+ return new (Context) MSPropertySubscriptExpr(
+ base, idx, Context.PseudoObjectTy, VK_LValue, OK_Ordinary, rbLoc);
+ }
+
// Use C++ overloaded-operator rules if either operand has record
// type. The spec says to do this if either type is *overloadable*,
// but enum types can't declare subscript operators or conversion
@@ -3991,6 +3984,139 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc);
}
+ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
+ Expr *LowerBound,
+ SourceLocation ColonLoc, Expr *Length,
+ SourceLocation RBLoc) {
+ if (Base->getType()->isPlaceholderType() &&
+ !Base->getType()->isSpecificPlaceholderType(
+ BuiltinType::OMPArraySection)) {
+ ExprResult Result = CheckPlaceholderExpr(Base);
+ if (Result.isInvalid())
+ return ExprError();
+ Base = Result.get();
+ }
+ if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(LowerBound);
+ if (Result.isInvalid())
+ return ExprError();
+ LowerBound = Result.get();
+ }
+ if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(Length);
+ if (Result.isInvalid())
+ return ExprError();
+ Length = Result.get();
+ }
+
+ // Build an unanalyzed expression if either operand is type-dependent.
+ if (Base->isTypeDependent() ||
+ (LowerBound &&
+ (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
+ (Length && (Length->isTypeDependent() || Length->isValueDependent()))) {
+ return new (Context)
+ OMPArraySectionExpr(Base, LowerBound, Length, Context.DependentTy,
+ VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+ }
+
+ // Perform default conversions.
+ QualType OriginalTy = OMPArraySectionExpr::getBaseOriginalType(Base);
+ QualType ResultTy;
+ if (OriginalTy->isAnyPointerType()) {
+ ResultTy = OriginalTy->getPointeeType();
+ } else if (OriginalTy->isArrayType()) {
+ ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
+ } else {
+ return ExprError(
+ Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
+ << Base->getSourceRange());
+ }
+ // C99 6.5.2.1p1
+ if (LowerBound) {
+ auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
+ LowerBound);
+ if (Res.isInvalid())
+ return ExprError(Diag(LowerBound->getExprLoc(),
+ diag::err_omp_typecheck_section_not_integer)
+ << 0 << LowerBound->getSourceRange());
+ LowerBound = Res.get();
+
+ if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
+ << 0 << LowerBound->getSourceRange();
+ }
+ if (Length) {
+ auto Res =
+ PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
+ if (Res.isInvalid())
+ return ExprError(Diag(Length->getExprLoc(),
+ diag::err_omp_typecheck_section_not_integer)
+ << 1 << Length->getSourceRange());
+ Length = Res.get();
+
+ if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
+ << 1 << Length->getSourceRange();
+ }
+
+ // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
+ // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
+ // type. Note that functions are not objects, and that (in C99 parlance)
+ // incomplete types are not object types.
+ if (ResultTy->isFunctionType()) {
+ Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
+ << ResultTy << Base->getSourceRange();
+ return ExprError();
+ }
+
+ if (RequireCompleteType(Base->getExprLoc(), ResultTy,
+ diag::err_omp_section_incomplete_type, Base))
+ return ExprError();
+
+ if (LowerBound) {
+ llvm::APSInt LowerBoundValue;
+ if (LowerBound->EvaluateAsInt(LowerBoundValue, Context)) {
+ // OpenMP 4.0, [2.4 Array Sections]
+ // The lower-bound and length must evaluate to non-negative integers.
+ if (LowerBoundValue.isNegative()) {
+ Diag(LowerBound->getExprLoc(), diag::err_omp_section_negative)
+ << 0 << LowerBoundValue.toString(/*Radix=*/10, /*Signed=*/true)
+ << LowerBound->getSourceRange();
+ return ExprError();
+ }
+ }
+ }
+
+ if (Length) {
+ llvm::APSInt LengthValue;
+ if (Length->EvaluateAsInt(LengthValue, Context)) {
+ // OpenMP 4.0, [2.4 Array Sections]
+ // The lower-bound and length must evaluate to non-negative integers.
+ if (LengthValue.isNegative()) {
+ Diag(Length->getExprLoc(), diag::err_omp_section_negative)
+ << 1 << LengthValue.toString(/*Radix=*/10, /*Signed=*/true)
+ << Length->getSourceRange();
+ return ExprError();
+ }
+ }
+ } else if (ColonLoc.isValid() &&
+ (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
+ !OriginalTy->isVariableArrayType()))) {
+ // OpenMP 4.0, [2.4 Array Sections]
+ // When the size of the array dimension is not known, the length must be
+ // specified explicitly.
+ Diag(ColonLoc, diag::err_omp_section_length_undefined)
+ << (!OriginalTy.isNull() && OriginalTy->isArrayType());
+ return ExprError();
+ }
+
+ return new (Context)
+ OMPArraySectionExpr(Base, LowerBound, Length, Context.OMPArraySectionTy,
+ VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+}
+
ExprResult
Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
@@ -4275,29 +4401,27 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
llvm::make_unique<FunctionCallCCC>(S, FuncName.getAsIdentifierInfo(),
Args.size(), ME),
Sema::CTK_ErrorRecovery)) {
- if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+ if (NamedDecl *ND = Corrected.getFoundDecl()) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(NameLoc, OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
- for (TypoCorrection::decl_iterator CD = Corrected.begin(),
- CDEnd = Corrected.end();
- CD != CDEnd; ++CD) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+ for (NamedDecl *CD : Corrected) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD))
S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
OCS);
}
switch (OCS.BestViableFunction(S, NameLoc, Best)) {
case OR_Success:
- ND = Best->Function;
+ ND = Best->FoundDecl;
Corrected.setCorrectionDecl(ND);
break;
default:
break;
}
}
- if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+ ND = ND->getUnderlyingDecl();
+ if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))
return Corrected;
- }
}
}
return TypoCorrection();
@@ -4433,7 +4557,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
bool IsListInitialization) {
unsigned NumParams = Proto->getNumParams();
bool Invalid = false;
- unsigned ArgIx = 0;
+ size_t ArgIx = 0;
// Continue to check argument types (even if we have too few/many args).
for (unsigned i = FirstParam; i < NumParams; i++) {
QualType ProtoArgType = Proto->getParamType(i);
@@ -4503,26 +4627,25 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
// return __unknown_anytype aren't *really* variadic.
if (Proto->getReturnType() == Context.UnknownAnyTy && FDecl &&
FDecl->isExternC()) {
- for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
+ for (Expr *A : Args.slice(ArgIx)) {
QualType paramType; // ignored
- ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType);
+ ExprResult arg = checkUnknownAnyArg(CallLoc, A, paramType);
Invalid |= arg.isInvalid();
AllArgs.push_back(arg.get());
}
// Otherwise do argument promotion, (C99 6.5.2.2p7).
} else {
- for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
- ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType,
- FDecl);
+ for (Expr *A : Args.slice(ArgIx)) {
+ ExprResult Arg = DefaultVariadicArgumentPromotion(A, CallType, FDecl);
Invalid |= Arg.isInvalid();
AllArgs.push_back(Arg.get());
}
}
// Check for array bounds violations.
- for (unsigned i = ArgIx, e = Args.size(); i != e; ++i)
- CheckArrayAccess(Args[i]);
+ for (Expr *A : Args.slice(ArgIx))
+ CheckArrayAccess(A);
}
return Invalid;
}
@@ -4623,7 +4746,9 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
// These are always invalid as call arguments and should be reported.
case BuiltinType::BoundMember:
case BuiltinType::BuiltinFn:
+ case BuiltinType::OMPArraySection:
return true;
+
}
llvm_unreachable("bad builtin type kind");
}
@@ -4647,7 +4772,7 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
}
/// If a builtin function has a pointer argument with no explicit address
-/// space, than it should be able to accept a pointer to any address
+/// space, then it should be able to accept a pointer to any address
/// space as input. In order to do this, we need to replace the
/// standard builtin declaration with one that uses the same address space
/// as the call.
@@ -4745,7 +4870,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// Pseudo-destructor calls should not have any arguments.
Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args)
<< FixItHint::CreateRemoval(
- SourceRange(ArgExprs[0]->getLocStart(),
+ SourceRange(ArgExprs.front()->getLocStart(),
ArgExprs.back()->getLocEnd()));
}
@@ -4802,14 +4927,10 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// We aren't supposed to apply this logic for if there's an '&' involved.
if (!find.HasFormOfMemberPointer) {
OverloadExpr *ovl = find.Expression;
- if (isa<UnresolvedLookupExpr>(ovl)) {
- UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))
return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs,
RParenLoc, ExecConfig);
- } else {
- return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs,
- RParenLoc);
- }
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc);
}
}
@@ -4832,7 +4953,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl);
if (FDecl && FDecl->getBuiltinID()) {
- // Rewrite the function decl for this builtin by replacing paramaters
+ // Rewrite the function decl for this builtin by replacing parameters
// with no explicit address space with the address space of the arguments
// in ArgExprs.
if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) {
@@ -4949,7 +5070,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (!Result.isUsable()) return ExprError();
TheCall = dyn_cast<CallExpr>(Result.get());
if (!TheCall) return Result;
- Args = ArrayRef<Expr *>(TheCall->getArgs(), TheCall->getNumArgs());
+ Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs());
}
// Bail out early if calling a builtin with custom typechecking.
@@ -5098,8 +5219,7 @@ ExprResult
Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
SourceLocation RParenLoc, Expr *InitExpr) {
assert(Ty && "ActOnCompoundLiteral(): missing type");
- // FIXME: put back this assert when initializers are worked out.
- //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
+ assert(InitExpr && "ActOnCompoundLiteral(): missing expression");
TypeSourceInfo *TInfo;
QualType literalType = GetTypeFromParser(Ty, &TInfo);
@@ -5280,13 +5400,13 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
return CK_IntegralToFloating;
case Type::STK_IntegralComplex:
Src = ImpCastExprToType(Src.get(),
- DestTy->castAs<ComplexType>()->getElementType(),
- CK_IntegralCast);
+ DestTy->castAs<ComplexType>()->getElementType(),
+ CK_IntegralCast);
return CK_IntegralRealToComplex;
case Type::STK_FloatingComplex:
Src = ImpCastExprToType(Src.get(),
- DestTy->castAs<ComplexType>()->getElementType(),
- CK_IntegralToFloating);
+ DestTy->castAs<ComplexType>()->getElementType(),
+ CK_IntegralToFloating);
return CK_FloatingRealToComplex;
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
@@ -5401,36 +5521,54 @@ static bool breakDownVectorType(QualType type, uint64_t &len,
return true;
}
-static bool VectorTypesMatch(Sema &S, QualType srcTy, QualType destTy) {
+/// Are the two types lax-compatible vector types? That is, given
+/// that one of them is a vector, do they have equal storage sizes,
+/// where the storage size is the number of elements times the element
+/// size?
+///
+/// This will also return false if either of the types is neither a
+/// vector nor a real type.
+bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
+ assert(destTy->isVectorType() || srcTy->isVectorType());
+
+ // Disallow lax conversions between scalars and ExtVectors (these
+ // conversions are allowed for other vector types because common headers
+ // depend on them). Most scalar OP ExtVector cases are handled by the
+ // splat path anyway, which does what we want (convert, not bitcast).
+ // What this rules out for ExtVectors is crazy things like char4*float.
+ if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
+ if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
+
uint64_t srcLen, destLen;
- QualType srcElt, destElt;
- if (!breakDownVectorType(srcTy, srcLen, srcElt)) return false;
- if (!breakDownVectorType(destTy, destLen, destElt)) return false;
+ QualType srcEltTy, destEltTy;
+ if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
+ if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
// ASTContext::getTypeSize will return the size rounded up to a
// power of 2, so instead of using that, we need to use the raw
// element size multiplied by the element count.
- uint64_t srcEltSize = S.Context.getTypeSize(srcElt);
- uint64_t destEltSize = S.Context.getTypeSize(destElt);
+ uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
+ uint64_t destEltSize = Context.getTypeSize(destEltTy);
return (srcLen * srcEltSize == destLen * destEltSize);
}
-/// Is this a legal conversion between two known vector types?
+/// Is this a legal conversion between two types, one of which is
+/// known to be a vector type?
bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
assert(destTy->isVectorType() || srcTy->isVectorType());
if (!Context.getLangOpts().LaxVectorConversions)
return false;
- return VectorTypesMatch(*this, srcTy, destTy);
+ return areLaxCompatibleVectorTypes(srcTy, destTy);
}
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
- if (Ty->isVectorType() || Ty->isIntegerType()) {
- if (!VectorTypesMatch(*this, Ty, VectorTy))
+ if (Ty->isVectorType() || Ty->isIntegralType(Context)) {
+ if (!areLaxCompatibleVectorTypes(Ty, VectorTy))
return Diag(R.getBegin(),
Ty->isVectorType() ?
diag::err_invalid_conversion_between_vectors :
@@ -5456,7 +5594,7 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
// In OpenCL, casts between vectors of different types are not allowed.
// (See OpenCL 6.2).
if (SrcTy->isVectorType()) {
- if (!VectorTypesMatch(*this, SrcTy, DestTy)
+ if (!areLaxCompatibleVectorTypes(SrcTy, DestTy)
|| (getLangOpts().OpenCL &&
(DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) {
Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
@@ -6358,7 +6496,7 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
static void SuggestParentheses(Sema &Self, SourceLocation Loc,
const PartialDiagnostic &Note,
SourceRange ParenRange) {
- SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
+ SourceLocation EndLoc = Self.getLocForEndOfToken(ParenRange.getEnd());
if (ParenRange.getBegin().isFileID() && ParenRange.getEnd().isFileID() &&
EndLoc.isValid()) {
Self.Diag(Loc, Note)
@@ -6371,7 +6509,9 @@ static void SuggestParentheses(Sema &Self, SourceLocation Loc,
}
static bool IsArithmeticOp(BinaryOperatorKind Opc) {
- return Opc >= BO_Mul && Opc <= BO_Shr;
+ return BinaryOperator::isAdditiveOp(Opc) ||
+ BinaryOperator::isMultiplicativeOp(Opc) ||
+ BinaryOperator::isShiftOp(Opc);
}
/// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary
@@ -6417,10 +6557,6 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
return false;
}
-static bool IsLogicOp(BinaryOperatorKind Opc) {
- return (Opc >= BO_LT && Opc <= BO_NE) || (Opc >= BO_LAnd && Opc <= BO_LOr);
-}
-
/// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type
/// or is a logical expression such as (x==y) which has int type, but is
/// commonly interpreted as boolean.
@@ -6430,7 +6566,7 @@ static bool ExprLooksBoolean(Expr *E) {
if (E->getType()->isBooleanType())
return true;
if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E))
- return IsLogicOp(OP->getOpcode());
+ return OP->isComparisonOp() || OP->isLogicalOp();
if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E))
return OP->getOpcode() == UO_LNot;
if (E->getType()->isPointerType())
@@ -6753,7 +6889,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc,
ExprResult RHSPtr = &RHSExpr;
CastKind K = CK_Invalid;
- return CheckAssignmentConstraints(LHSType, RHSPtr, K);
+ return CheckAssignmentConstraints(LHSType, RHSPtr, K, /*ConvertRHS=*/false);
}
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
@@ -6775,7 +6911,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc,
/// Sets 'Kind' for any result kind except Incompatible.
Sema::AssignConvertType
Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
- CastKind &Kind) {
+ CastKind &Kind, bool ConvertRHS) {
QualType RHSType = RHS.get()->getType();
QualType OrigLHSType = LHSType;
@@ -6797,7 +6933,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind);
if (result != Compatible)
return result;
- if (Kind != CK_NoOp)
+ if (Kind != CK_NoOp && ConvertRHS)
RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind);
Kind = CK_NonAtomicToAtomic;
return Compatible;
@@ -6827,7 +6963,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// CK_VectorSplat does T -> vector T, so first cast to the
// element type.
QualType elType = cast<ExtVectorType>(LHSType)->getElementType();
- if (elType != RHSType) {
+ if (elType != RHSType && ConvertRHS) {
Kind = PrepareScalarCast(RHS, elType);
RHS = ImpCastExprToType(RHS.get(), elType, Kind);
}
@@ -6860,7 +6996,8 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// Arithmetic conversions.
if (LHSType->isArithmeticType() && RHSType->isArithmeticType() &&
!(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) {
- Kind = PrepareScalarCast(RHS, LHSType);
+ if (ConvertRHS)
+ Kind = PrepareScalarCast(RHS, LHSType);
return Compatible;
}
@@ -6985,7 +7122,8 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// Only under strict condition T^ is compatible with an Objective-C pointer.
if (RHSType->isBlockPointerType() &&
LHSType->isBlockCompatibleObjCPointerType(Context)) {
- maybeExtendBlockObject(RHS);
+ if (ConvertRHS)
+ maybeExtendBlockObject(RHS);
Kind = CK_BlockPointerToObjCPointerCast;
return Compatible;
}
@@ -7111,9 +7249,16 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
}
Sema::AssignConvertType
-Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
+Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
bool Diagnose,
- bool DiagnoseCFAudited) {
+ bool DiagnoseCFAudited,
+ bool ConvertRHS) {
+ // If ConvertRHS is false, we want to leave the caller's RHS untouched. Sadly,
+ // we can't avoid *all* modifications at the moment, so we need some somewhere
+ // to put the updated value.
+ ExprResult LocalRHS = CallerRHS;
+ ExprResult &RHS = ConvertRHS ? CallerRHS : LocalRHS;
+
if (getLangOpts().CPlusPlus) {
if (!LHSType->isRecordType() && !LHSType->isAtomicType()) {
// C++ 5.17p3: If the left operand is not of class type, the
@@ -7151,6 +7296,15 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// structures.
// FIXME: We also fall through for atomics; not sure what should
// happen there, though.
+ } else if (RHS.get()->getType() == Context.OverloadTy) {
+ // As a set of extensions to C, we support overloading on functions. These
+ // functions need to be resolved here.
+ DeclAccessPair DAP;
+ if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction(
+ RHS.get(), LHSType, /*Complain=*/false, DAP))
+ RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD);
+ else
+ return Incompatible;
}
// C99 6.5.16.1p1: the left operand is a pointer and the right is
@@ -7162,7 +7316,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
CastKind Kind;
CXXCastPath Path;
CheckPointerConversion(RHS.get(), LHSType, Kind, Path, false);
- RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path);
+ if (ConvertRHS)
+ RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path);
return Compatible;
}
@@ -7173,7 +7328,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
//
// Suppress this for references: C++ 8.5.3p5.
if (!LHSType->isReferenceType()) {
- RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
+ // FIXME: We potentially allocate here even if ConvertRHS is false.
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get(), Diagnose);
if (RHS.isInvalid())
return Incompatible;
}
@@ -7189,7 +7345,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
CastKind Kind = CK_Invalid;
Sema::AssignConvertType result =
- CheckAssignmentConstraints(LHSType, RHS, Kind);
+ CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS);
// C99 6.5.16.1p2: The value of the right operand is converted to the
// type of the assignment expression.
@@ -7211,7 +7367,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
return Compatible;
}
- RHS = ImpCastExprToType(E, Ty, Kind);
+ if (ConvertRHS)
+ RHS = ImpCastExprToType(E, Ty, Kind);
}
return result;
}
@@ -7374,6 +7531,18 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
return QualType();
}
+ // OpenCL V1.1 6.2.6.p1:
+ // If the operands are of more than one vector type, then an error shall
+ // occur. Implicit conversions between vector types are not permitted, per
+ // section 6.2.1.
+ if (getLangOpts().OpenCL &&
+ RHSVecType && isa<ExtVectorType>(RHSVecType) &&
+ LHSVecType && isa<ExtVectorType>(LHSVecType)) {
+ Diag(Loc, diag::err_opencl_implicit_vector_conversion) << LHSType
+ << RHSType;
+ return QualType();
+ }
+
// Otherwise, use the generic diagnostic.
Diag(Loc, diag::err_typecheck_vector_not_convertable)
<< LHSType << RHSType
@@ -7420,6 +7589,18 @@ static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS,
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
+static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc, bool IsDiv) {
+ // Check for division/remainder by zero.
+ llvm::APSInt RHSValue;
+ if (!RHS.get()->isValueDependent() &&
+ RHS.get()->EvaluateAsInt(RHSValue, S.Context) && RHSValue == 0)
+ S.DiagRuntimeBehavior(Loc, RHS.get(),
+ S.PDiag(diag::warn_remainder_division_by_zero)
+ << IsDiv << RHS.get()->getSourceRange());
+}
+
QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
bool IsCompAssign, bool IsDiv) {
@@ -7438,15 +7619,8 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
if (compType.isNull() || !compType->isArithmeticType())
return InvalidOperands(Loc, LHS, RHS);
-
- // Check for division by zero.
- 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());
-
+ if (IsDiv)
+ DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
return compType;
}
@@ -7470,15 +7644,7 @@ QualType Sema::CheckRemainderOperands(
if (compType.isNull() || !compType->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
-
- // Check for remainder by zero.
- 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());
-
+ DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
return compType;
}
@@ -7596,7 +7762,7 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType();
// if both are pointers check if operation is valid wrt address spaces
- if (isLHSPointer && isRHSPointer) {
+ if (S.getLangOpts().OpenCL && isLHSPointer && isRHSPointer) {
const PointerType *lhsPtr = LHSExpr->getType()->getAs<PointerType>();
const PointerType *rhsPtr = RHSExpr->getType()->getAs<PointerType>();
if (!lhsPtr->isAddressSpaceOverlapping(*rhsPtr)) {
@@ -7669,7 +7835,7 @@ 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());
+ SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd());
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
<< FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
@@ -7719,7 +7885,7 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
// Only print a fixit for str + char, not for char + str.
if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) {
- SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
+ SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd());
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
<< FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
@@ -7739,9 +7905,10 @@ static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc,
<< RHSExpr->getSourceRange();
}
-QualType Sema::CheckAdditionOperands( // C99 6.5.6
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc,
- QualType* CompLHSTy) {
+// C99 6.5.6
+QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc, BinaryOperatorKind Opc,
+ QualType* CompLHSTy) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
if (LHS.get()->getType()->isVectorType() ||
@@ -7917,7 +8084,7 @@ static bool isScopedEnumerationType(QualType T) {
}
static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, unsigned Opc,
+ SourceLocation Loc, BinaryOperatorKind Opc,
QualType LHSType) {
// OpenCL 6.3j: shift values are effectively % word size of LHS (more defined),
// so skip remaining warnings as we don't want to modify values within Sema.
@@ -8060,7 +8227,7 @@ static QualType checkOpenCLVectorShift(Sema &S,
// C99 6.5.7
QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, unsigned Opc,
+ SourceLocation Loc, BinaryOperatorKind Opc,
bool IsCompAssign) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
@@ -8365,9 +8532,9 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
if (BinaryOperator::isEqualityOp(Opc) &&
hasIsEqualMethod(S, LHS.get(), RHS.get())) {
SourceLocation Start = LHS.get()->getLocStart();
- SourceLocation End = S.PP.getLocForEndOfToken(RHS.get()->getLocEnd());
+ SourceLocation End = S.getLocForEndOfToken(RHS.get()->getLocEnd());
CharSourceRange OpRange =
- CharSourceRange::getCharRange(Loc, S.PP.getLocForEndOfToken(Loc));
+ CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
S.Diag(Loc, diag::note_objc_literal_comparison_isequal)
<< FixItHint::CreateInsertion(Start, Opc == BO_EQ ? "[" : "![")
@@ -8379,20 +8546,17 @@ 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;
-
+ BinaryOperatorKind Opc) {
// 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;
+ if (RHS.get()->isKnownToHaveBooleanValue()) return;
// Make sure that the something in !something is not bool.
Expr *SubExpr = UO->getSubExpr()->IgnoreImpCasts();
- if (SubExpr->getType()->isBooleanType()) return;
+ if (SubExpr->isKnownToHaveBooleanValue()) return;
// Emit warning.
S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_comparison)
@@ -8401,7 +8565,7 @@ static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
// First note suggest !(x < y)
SourceLocation FirstOpen = SubExpr->getLocStart();
SourceLocation FirstClose = RHS.get()->getLocEnd();
- FirstClose = S.getPreprocessor().getLocForEndOfToken(FirstClose);
+ FirstClose = S.getLocForEndOfToken(FirstClose);
if (FirstClose.isInvalid())
FirstOpen = SourceLocation();
S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix)
@@ -8411,7 +8575,7 @@ static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
// Second note suggests (!x) < y
SourceLocation SecondOpen = LHS.get()->getLocStart();
SourceLocation SecondClose = LHS.get()->getLocEnd();
- SecondClose = S.getPreprocessor().getLocForEndOfToken(SecondClose);
+ SecondClose = S.getLocForEndOfToken(SecondClose);
if (SecondClose.isInvalid())
SecondOpen = SourceLocation();
S.Diag(UO->getOperatorLoc(), diag::note_logical_not_silence_with_parens)
@@ -8437,12 +8601,10 @@ static ValueDecl *getCompareDecl(Expr *E) {
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, unsigned OpaqueOpc,
+ SourceLocation Loc, BinaryOperatorKind Opc,
bool IsRelational) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true);
- BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc;
-
// Handle vector comparisons separately.
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType())
@@ -8455,7 +8617,7 @@ 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);
+ diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, Opc);
if (!LHSType->hasFloatingRepresentation() &&
!(LHSType->isBlockPointerType() && IsRelational) &&
@@ -8628,12 +8790,15 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false);
}
if (LCanPointeeTy != RCanPointeeTy) {
- const PointerType *lhsPtr = LHSType->getAs<PointerType>();
- if (!lhsPtr->isAddressSpaceOverlapping(*RHSType->getAs<PointerType>())) {
- Diag(Loc,
- diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
- << LHSType << RHSType << 0 /* comparison */
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ // Treat NULL constant as a special case in OpenCL.
+ if (getLangOpts().OpenCL && !LHSIsNull && !RHSIsNull) {
+ const PointerType *LHSPtr = LHSType->getAs<PointerType>();
+ if (!LHSPtr->isAddressSpaceOverlapping(*RHSType->getAs<PointerType>())) {
+ Diag(Loc,
+ diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
+ << LHSType << RHSType << 0 /* comparison */
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ }
}
unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace();
unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace();
@@ -8941,9 +9106,10 @@ inline QualType Sema::CheckBitwiseOperands(
return InvalidOperands(Loc, LHS, RHS);
}
-inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc) {
-
+// C99 6.5.[13,14]
+inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc,
+ BinaryOperatorKind Opc) {
// Check vector operands differently.
if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType())
return CheckVectorLogicalOperands(LHS, RHS, Loc);
@@ -8972,18 +9138,14 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator)
<< (Opc == BO_LAnd ? "&" : "|")
<< FixItHint::CreateReplacement(SourceRange(
- Loc, Lexer::getLocForEndOfToken(Loc, 0, getSourceManager(),
- getLangOpts())),
+ Loc, getLocForEndOfToken(Loc)),
Opc == BO_LAnd ? "&" : "|");
if (Opc == BO_LAnd)
// Suggest replacing "Foo() && kNonZero" with "Foo()"
Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant)
<< FixItHint::CreateRemoval(
- SourceRange(
- Lexer::getLocForEndOfToken(LHS.get()->getLocEnd(),
- 0, getSourceManager(),
- getLangOpts()),
- RHS.get()->getLocEnd()));
+ SourceRange(getLocForEndOfToken(LHS.get()->getLocEnd()),
+ RHS.get()->getLocEnd()));
}
}
@@ -9161,7 +9323,7 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
// Function calls
const FunctionDecl *FD = CE->getDirectCallee();
- if (!IsTypeModifiable(FD->getReturnType(), IsDereference)) {
+ if (FD && !IsTypeModifiable(FD->getReturnType(), IsDereference)) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
<< ConstFunction << FD;
@@ -9510,7 +9672,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
return QualType();
}
// Increment of bool sets it to true, but is deprecated.
- S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+ S.Diag(OpLoc, S.getLangOpts().CPlusPlus1z ? diag::ext_increment_bool
+ : 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;
@@ -9710,6 +9874,12 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// expressions here, but the result of one is always an lvalue anyway.
}
ValueDecl *dcl = getPrimaryDecl(op);
+
+ if (auto *FD = dyn_cast_or_null<FunctionDecl>(dcl))
+ if (!checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+ op->getLocStart()))
+ return QualType();
+
Expr::LValueClassification lval = op->ClassifyLValue(Context);
unsigned AddressOfError = AO_No_Error;
@@ -9763,8 +9933,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
QualType MPTy = Context.getMemberPointerType(
op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ // Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- RequireCompleteType(OpLoc, MPTy, 0);
+ (void)isCompleteType(OpLoc, MPTy);
return MPTy;
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
@@ -9819,8 +9990,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
QualType MPTy = Context.getMemberPointerType(
op->getType(),
Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ // Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- RequireCompleteType(OpLoc, MPTy, 0);
+ (void)isCompleteType(OpLoc, MPTy);
return MPTy;
}
}
@@ -10121,6 +10293,20 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
return ExprError();
}
+ if (getLangOpts().OpenCL) {
+ // OpenCLC v2.0 s6.13.11.1 allows atomic variables to be initialized by
+ // the ATOMIC_VAR_INIT macro.
+ if (LHSExpr->getType()->isAtomicType() ||
+ RHSExpr->getType()->isAtomicType()) {
+ SourceRange SR(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+ if (BO_Assign == Opc)
+ Diag(OpLoc, diag::err_atomic_init_constant) << SR;
+ else
+ ResultTy = InvalidOperands(OpLoc, LHS, RHS);
+ return ExprError();
+ }
+ }
+
switch (Opc) {
case BO_Assign:
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
@@ -10211,7 +10397,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_AndAssign:
case BO_OrAssign: // fallthrough
- DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
+ DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
case BO_XorAssign:
CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, true);
CompLHSTy = CompResultTy;
@@ -10238,7 +10424,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
&Context.Idents.get("object_setClass"),
SourceLocation(), LookupOrdinaryName);
if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) {
- SourceLocation RHSLocEnd = PP.getLocForEndOfToken(RHS.get()->getLocEnd());
+ SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getLocEnd());
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign) <<
FixItHint::CreateInsertion(LHS.get()->getLocStart(), "object_setClass(") <<
FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc), ",") <<
@@ -10274,17 +10460,17 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
BinaryOperator *LHSBO = dyn_cast<BinaryOperator>(LHSExpr);
BinaryOperator *RHSBO = dyn_cast<BinaryOperator>(RHSExpr);
- // Check that one of the sides is a comparison operator.
+ // Check that one of the sides is a comparison operator and the other isn't.
bool isLeftComp = LHSBO && LHSBO->isComparisonOp();
bool isRightComp = RHSBO && RHSBO->isComparisonOp();
- if (!isLeftComp && !isRightComp)
+ if (isLeftComp == isRightComp)
return;
// Bitwise operations are sometimes used as eager logical ops.
// Don't diagnose this.
bool isLeftBitwise = LHSBO && LHSBO->isBitwiseOp();
bool isRightBitwise = RHSBO && RHSBO->isBitwiseOp();
- if ((isLeftComp || isLeftBitwise) && (isRightComp || isRightBitwise))
+ if (isLeftBitwise || isRightBitwise)
return;
SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(),
@@ -10306,21 +10492,6 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
ParensRange);
}
-/// \brief It accepts a '&' expr that is inside a '|' one.
-/// Emit a diagnostic together with a fixit hint that wraps the '&' expression
-/// in parentheses.
-static void
-EmitDiagnosticForBitwiseAndInBitwiseOr(Sema &Self, SourceLocation OpLoc,
- BinaryOperator *Bop) {
- assert(Bop->getOpcode() == BO_And);
- Self.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_and_in_bitwise_or)
- << Bop->getSourceRange() << OpLoc;
- SuggestParentheses(Self, Bop->getOperatorLoc(),
- Self.PDiag(diag::note_precedence_silence)
- << Bop->getOpcodeStr(),
- Bop->getSourceRange());
-}
-
/// \brief It accepts a '&&' expr that is inside a '||' one.
/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression
/// in parentheses.
@@ -10389,12 +10560,21 @@ static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
}
}
-/// \brief Look for '&' in the left or right hand of a '|' expr.
-static void DiagnoseBitwiseAndInBitwiseOr(Sema &S, SourceLocation OpLoc,
- Expr *OrArg) {
- if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrArg)) {
- if (Bop->getOpcode() == BO_And)
- return EmitDiagnosticForBitwiseAndInBitwiseOr(S, OpLoc, Bop);
+/// \brief Look for bitwise op in the left or right hand of a bitwise op with
+/// lower precedence and emit a diagnostic together with a fixit hint that wraps
+/// the '&' expression in parentheses.
+static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc,
+ SourceLocation OpLoc, Expr *SubExpr) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(SubExpr)) {
+ if (Bop->isBitwiseOp() && Bop->getOpcode() < Opc) {
+ S.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_op_in_bitwise_op)
+ << Bop->getOpcodeStr() << BinaryOperator::getOpcodeStr(Opc)
+ << Bop->getSourceRange() << OpLoc;
+ SuggestParentheses(S, Bop->getOperatorLoc(),
+ S.PDiag(diag::note_precedence_silence)
+ << Bop->getOpcodeStr(),
+ Bop->getSourceRange());
+ }
}
}
@@ -10449,9 +10629,10 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
DiagnoseBitwisePrecedence(Self, Opc, OpLoc, LHSExpr, RHSExpr);
// Diagnose "arg1 & arg2 | arg3"
- if (Opc == BO_Or && !OpLoc.isMacroID()/* Don't warn in macros. */) {
- DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, LHSExpr);
- DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, RHSExpr);
+ if ((Opc == BO_Or || Opc == BO_Xor) &&
+ !OpLoc.isMacroID()/* Don't warn in macros. */) {
+ DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, LHSExpr);
+ DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, RHSExpr);
}
// Warn about arg1 || arg2 && arg3, as GCC 4.3+ does.
@@ -10593,6 +10774,14 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
+ if (getLangOpts().OpenCL) {
+ // The only legal unary operation for atomics is '&'.
+ if (Opc != UO_AddrOf && InputExpr->getType()->isAtomicType()) {
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << InputExpr->getType()
+ << Input.get()->getSourceRange());
+ }
+ }
switch (Opc) {
case UO_PreInc:
case UO_PreDec:
@@ -10735,6 +10924,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
}
break;
case UO_Extension:
+ case UO_Coawait:
resultType = Input.get()->getType();
VK = Input.get()->getValueKind();
OK = Input.get()->getObjectKind();
@@ -10778,10 +10968,8 @@ static bool isQualifiedMemberAccess(Expr *E) {
if (!ULE->getQualifier())
return false;
- for (UnresolvedLookupExpr::decls_iterator D = ULE->decls_begin(),
- DEnd = ULE->decls_end();
- D != DEnd; ++D) {
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*D)) {
+ for (NamedDecl *D : ULE->decls()) {
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isInstance())
return true;
} else {
@@ -10971,8 +11159,7 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
TypeSourceInfo *TInfo,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
+ ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc) {
QualType ArgTy = TInfo->getType();
bool Dependent = ArgTy->isDependentType();
@@ -10996,17 +11183,15 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// GCC extension, diagnose them.
// FIXME: This diagnostic isn't actually visible because the location is in
// a system header!
- if (NumComponents != 1)
+ if (Components.size() != 1)
Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
- << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
+ << SourceRange(Components[1].LocStart, Components.back().LocEnd);
bool DidWarnAboutNonPOD = false;
QualType CurrentType = ArgTy;
- typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
SmallVector<OffsetOfNode, 4> Comps;
SmallVector<Expr*, 4> Exprs;
- for (unsigned i = 0; i != NumComponents; ++i) {
- const OffsetOfComponent &OC = CompPtr[i];
+ for (const OffsetOfComponent &OC : Components) {
if (OC.isBrackets) {
// Offset of an array sub-field. TODO: Should we allow vector elements?
if (!CurrentType->isDependentType()) {
@@ -11074,7 +11259,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
if (!IsSafe && !DidWarnAboutNonPOD &&
DiagRuntimeBehavior(BuiltinLoc, nullptr,
PDiag(DiagID)
- << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
+ << SourceRange(Components[0].LocStart, OC.LocEnd)
<< CurrentType))
DidWarnAboutNonPOD = true;
}
@@ -11113,7 +11298,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// If the member was found in a base class, introduce OffsetOfNodes for
// the base class indirections.
CXXBasePaths Paths;
- if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
+ if (IsDerivedFrom(OC.LocStart, CurrentType, Context.getTypeDeclType(Parent),
+ Paths)) {
if (Paths.getDetectedVirtual()) {
Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base)
<< MemberDecl->getDeclName()
@@ -11122,9 +11308,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
}
CXXBasePath &Path = Paths.front();
- for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
- B != BEnd; ++B)
- Comps.push_back(OffsetOfNode(B->Base));
+ for (const CXXBasePathElement &B : Path)
+ Comps.push_back(OffsetOfNode(B.Base));
}
if (IndirectMemberDecl) {
@@ -11147,8 +11332,7 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
SourceLocation BuiltinLoc,
SourceLocation TypeLoc,
ParsedType ParsedArgTy,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
+ ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc) {
TypeSourceInfo *ArgTInfo;
@@ -11159,8 +11343,7 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
if (!ArgTInfo)
ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
- return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
- RParenLoc);
+ return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, Components, RParenLoc);
}
@@ -11394,16 +11577,14 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// Set the captured variables on the block.
// FIXME: Share capture structure between BlockDecl and CapturingScopeInfo!
SmallVector<BlockDecl::Capture, 4> Captures;
- for (unsigned i = 0, e = BSI->Captures.size(); i != e; i++) {
- CapturingScopeInfo::Capture &Cap = BSI->Captures[i];
+ for (CapturingScopeInfo::Capture &Cap : BSI->Captures) {
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
Cap.isNested(), Cap.getInitExpr());
Captures.push_back(NewCap);
}
- BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(),
- BSI->CXXThisCaptureIndex != 0);
+ BSI->TheDecl->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
// If the user wrote a function type in some form, try to use that.
if (!BSI->FunctionType.isNull()) {
@@ -11495,43 +11676,57 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
Expr *E, TypeSourceInfo *TInfo,
SourceLocation RPLoc) {
Expr *OrigExpr = E;
+ bool IsMS = false;
+
+ // It might be a __builtin_ms_va_list. (But don't ever mark a va_arg()
+ // as Microsoft ABI on an actual Microsoft platform, where
+ // __builtin_ms_va_list and __builtin_va_list are the same.)
+ if (!E->isTypeDependent() && Context.getTargetInfo().hasBuiltinMSVaList() &&
+ Context.getTargetInfo().getBuiltinVaListKind() != TargetInfo::CharPtrBuiltinVaList) {
+ QualType MSVaListType = Context.getBuiltinMSVaListType();
+ if (Context.hasSameType(MSVaListType, E->getType())) {
+ if (CheckForModifiableLvalue(E, BuiltinLoc, *this))
+ return ExprError();
+ IsMS = true;
+ }
+ }
// Get the va_list type
QualType VaListType = Context.getBuiltinVaListType();
- if (VaListType->isArrayType()) {
- // Deal with implicit array decay; for example, on x86-64,
- // va_list is an array, but it's supposed to decay to
- // a pointer for va_arg.
- VaListType = Context.getArrayDecayedType(VaListType);
- // Make sure the input expression also decays appropriately.
- ExprResult Result = UsualUnaryConversions(E);
- if (Result.isInvalid())
- return ExprError();
- E = Result.get();
- } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) {
- // If va_list is a record type and we are compiling in C++ mode,
- // check the argument using reference binding.
- InitializedEntity Entity
- = InitializedEntity::InitializeParameter(Context,
- Context.getLValueReferenceType(VaListType), false);
- ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E);
- if (Init.isInvalid())
- return ExprError();
- E = Init.getAs<Expr>();
- } else {
- // Otherwise, the va_list argument must be an l-value because
- // it is modified by va_arg.
- if (!E->isTypeDependent() &&
- CheckForModifiableLvalue(E, BuiltinLoc, *this))
- return ExprError();
+ if (!IsMS) {
+ if (VaListType->isArrayType()) {
+ // Deal with implicit array decay; for example, on x86-64,
+ // va_list is an array, but it's supposed to decay to
+ // a pointer for va_arg.
+ VaListType = Context.getArrayDecayedType(VaListType);
+ // Make sure the input expression also decays appropriately.
+ ExprResult Result = UsualUnaryConversions(E);
+ if (Result.isInvalid())
+ return ExprError();
+ E = Result.get();
+ } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) {
+ // If va_list is a record type and we are compiling in C++ mode,
+ // check the argument using reference binding.
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, Context.getLValueReferenceType(VaListType), false);
+ ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E);
+ if (Init.isInvalid())
+ return ExprError();
+ E = Init.getAs<Expr>();
+ } else {
+ // Otherwise, the va_list argument must be an l-value because
+ // it is modified by va_arg.
+ if (!E->isTypeDependent() &&
+ CheckForModifiableLvalue(E, BuiltinLoc, *this))
+ return ExprError();
+ }
}
- if (!E->isTypeDependent() &&
- !Context.hasSameType(VaListType, E->getType())) {
+ if (!IsMS && !E->isTypeDependent() &&
+ !Context.hasSameType(VaListType, E->getType()))
return ExprError(Diag(E->getLocStart(),
diag::err_first_argument_to_va_arg_not_of_type_va_list)
<< OrigExpr->getType() << E->getSourceRange());
- }
if (!TInfo->getType()->isDependentType()) {
if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
@@ -11573,7 +11768,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
}
QualType T = TInfo->getType().getNonLValueExprType(Context);
- return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T);
+ return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T, IsMS);
}
ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
@@ -11627,6 +11822,25 @@ Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp) {
return true;
}
+static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType,
+ const Expr *SrcExpr) {
+ if (!DstType->isFunctionPointerType() ||
+ !SrcExpr->getType()->isFunctionType())
+ return false;
+
+ auto *DRE = dyn_cast<DeclRefExpr>(SrcExpr->IgnoreParenImpCasts());
+ if (!DRE)
+ return false;
+
+ auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (!FD)
+ return false;
+
+ return !S.checkAddressOfFunctionIsAvailable(FD,
+ /*Complain=*/true,
+ SrcExpr->getLocStart());
+}
+
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
@@ -11759,6 +11973,12 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
DiagKind = diag::err_arc_weak_unavailable_assign;
break;
case Incompatible:
+ if (maybeDiagnoseAssignmentToFunction(*this, DstType, SrcExpr)) {
+ if (Complained)
+ *Complained = true;
+ return true;
+ }
+
DiagKind = diag::err_typecheck_convert_incompatible;
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
MayHaveConvFixit = true;
@@ -11797,9 +12017,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
// If we can fix the conversion, suggest the FixIts.
assert(ConvHints.isNull() || Hint.isNull());
if (!ConvHints.isNull()) {
- for (std::vector<FixItHint>::iterator HI = ConvHints.Hints.begin(),
- HE = ConvHints.Hints.end(); HI != HE; ++HI)
- FDiag << *HI;
+ for (FixItHint &H : ConvHints.Hints)
+ FDiag << H;
} else {
FDiag << Hint;
}
@@ -11816,7 +12035,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
if (SecondType == Context.OverloadTy)
NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
- FirstType);
+ FirstType, /*TakingAddress=*/true);
if (CheckInferredResultType)
EmitRelatedResultTypeNote(SrcExpr);
@@ -11974,16 +12193,16 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
if (!Folded || !AllowFold) {
if (!Diagnoser.Suppress) {
Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange());
- for (unsigned I = 0, N = Notes.size(); I != N; ++I)
- Diag(Notes[I].first, Notes[I].second);
+ for (const PartialDiagnosticAt &Note : Notes)
+ Diag(Note.first, Note.second);
}
return ExprError();
}
Diagnoser.diagnoseFold(*this, DiagLoc, E->getSourceRange());
- for (unsigned I = 0, N = Notes.size(); I != N; ++I)
- Diag(Notes[I].first, Notes[I].second);
+ for (const PartialDiagnosticAt &Note : Notes)
+ Diag(Note.first, Note.second);
if (Result)
*Result = EvalResult.Val.getInt();
@@ -12417,10 +12636,15 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDec
// Compute the type of an expression that refers to this variable.
DeclRefType = CaptureType.getNonReferenceType();
-
+
+ // Similarly to mutable captures in lambda, all the OpenMP captures by copy
+ // are mutable in the sense that user can change their value - they are
+ // private instances of the captured declarations.
const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
if (Cap.isCopyCapture() &&
- !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable))
+ !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable) &&
+ !(isa<CapturedRegionScopeInfo>(CSI) &&
+ cast<CapturedRegionScopeInfo>(CSI)->CapRegionKind == CR_OpenMP))
DeclRefType.addConst();
return true;
}
@@ -12608,9 +12832,17 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
// By default, capture variables by reference.
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
- if (S.getLangOpts().OpenMP && S.IsOpenMPCapturedVar(Var))
- DeclRefType = DeclRefType.getUnqualifiedType();
- CaptureType = S.Context.getLValueReferenceType(DeclRefType);
+ if (S.getLangOpts().OpenMP) {
+ ByRef = S.IsOpenMPCapturedByRef(Var, RSI);
+ if (S.IsOpenMPCapturedVar(Var))
+ DeclRefType = DeclRefType.getUnqualifiedType();
+ }
+
+ if (ByRef)
+ CaptureType = S.Context.getLValueReferenceType(DeclRefType);
+ else
+ CaptureType = DeclRefType;
+
Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
// The current implementation assumes that all variables are captured
@@ -12836,21 +13068,6 @@ bool Sema::tryCaptureVariable(
if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
DeclRefType))
break;
- if (getLangOpts().OpenMP) {
- if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
- // OpenMP private variables should not be captured in outer scope, so
- // just break here.
- if (RSI->CapRegionKind == CR_OpenMP) {
- if (isOpenMPPrivateVar(Var, OpenMPLevel)) {
- Nested = true;
- DeclRefType = DeclRefType.getUnqualifiedType();
- CaptureType = Context.getLValueReferenceType(DeclRefType);
- break;
- }
- ++OpenMPLevel;
- }
- }
- }
// 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
@@ -12996,6 +13213,29 @@ bool Sema::tryCaptureVariable(
} while (!QTy.isNull() && QTy->isVariablyModifiedType());
}
+ if (getLangOpts().OpenMP) {
+ if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+ // OpenMP private variables should not be captured in outer scope, so
+ // just break here. Similarly, global variables that are captured in a
+ // target region should not be captured outside the scope of the region.
+ if (RSI->CapRegionKind == CR_OpenMP) {
+ auto isTargetCap = isOpenMPTargetCapturedVar(Var, OpenMPLevel);
+ // When we detect target captures we are looking from inside the
+ // target region, therefore we need to propagate the capture from the
+ // enclosing region. Therefore, the capture is not initially nested.
+ if (isTargetCap)
+ FunctionScopesIndex--;
+
+ if (isTargetCap || isOpenMPPrivateVar(Var, OpenMPLevel)) {
+ Nested = !isTargetCap;
+ DeclRefType = DeclRefType.getUnqualifiedType();
+ CaptureType = Context.getLValueReferenceType(DeclRefType);
+ break;
+ }
+ ++OpenMPLevel;
+ }
+ }
+ }
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) {
// No capture-default, and this is not an explicit capture
// so cannot capture this variable.
@@ -13152,15 +13392,13 @@ ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
}
void Sema::CleanupVarDeclMarking() {
- for (llvm::SmallPtrSetIterator<Expr*> i = MaybeODRUseExprs.begin(),
- e = MaybeODRUseExprs.end();
- i != e; ++i) {
+ for (Expr *E : MaybeODRUseExprs) {
VarDecl *Var;
SourceLocation Loc;
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*i)) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
Var = cast<VarDecl>(DRE->getDecl());
Loc = DRE->getLocation();
- } else if (MemberExpr *ME = dyn_cast<MemberExpr>(*i)) {
+ } else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
Var = cast<VarDecl>(ME->getMemberDecl());
Loc = ME->getMemberLoc();
} else {
@@ -13217,7 +13455,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
}
if (!isTemplateInstantiation(TSK))
- return;
+ return;
// Instantiate, but do not mark as odr-used, variable templates.
MarkODRUsed = false;
@@ -13316,7 +13554,8 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
if (!MD)
return;
// Only attempt to devirtualize if this is truly a virtual call.
- bool IsVirtualCall = MD->isVirtual() && !ME->hasQualifier();
+ bool IsVirtualCall = MD->isVirtual() &&
+ ME->performsVirtualDispatch(SemaRef.getLangOpts());
if (!IsVirtualCall)
return;
const Expr *Base = ME->getBase();
@@ -13350,7 +13589,7 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
// expression, is odr-used, unless it is a pure virtual function and its
// name is not explicitly qualified.
bool OdrUse = true;
- if (!E->hasQualifier()) {
+ if (E->performsVirtualDispatch(getLangOpts())) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl()))
if (Method->isPure())
OdrUse = false;
@@ -13633,7 +13872,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
Diag(Loc, diagnostic) << E->getSourceRange();
SourceLocation Open = E->getLocStart();
- SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
+ SourceLocation Close = getLocForEndOfToken(E->getSourceRange().getEnd());
Diag(Loc, diag::note_condition_assign_silence)
<< FixItHint::CreateInsertion(Open, "(")
<< FixItHint::CreateInsertion(Close, ")");
@@ -14309,6 +14548,11 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
return ExprError();
}
+ // Expressions of unknown type.
+ case BuiltinType::OMPArraySection:
+ Diag(E->getLocStart(), diag::err_omp_array_section_use);
+ return ExprError();
+
// Everything else should be impossible.
#define BUILTIN_TYPE(Id, SingletonId) \
case BuiltinType::Id:
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 9ad5aa59b68a..2ad595f3a814 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1031,6 +1031,11 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc);
}
+ // C++14 [expr.type.conv]p2: The expression T(), where T is a
+ // simple-type-specifier or typename-specifier for a non-array complete
+ // object type or the (possibly cv-qualified) void type, creates a prvalue
+ // of the specified type, whose value is that produced by value-initializing
+ // an object of type T.
QualType ElemTy = Ty;
if (Ty->isArrayType()) {
if (!ListInitialization)
@@ -1039,6 +1044,10 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
ElemTy = Context.getBaseElementType(Ty);
}
+ if (!ListInitialization && Ty->isFunctionType())
+ return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_function_type)
+ << FullRange);
+
if (!Ty->isVoidType() &&
RequireCompleteType(TyBeginLoc, ElemTy,
diag::err_invalid_incomplete_type_use, FullRange))
@@ -2256,6 +2265,9 @@ FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
"found an unexpected usual deallocation function");
}
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads)
+ EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
+
assert(Matches.size() == 1 &&
"unexpectedly have multiple usual deallocation functions");
return Matches.front();
@@ -2287,6 +2299,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
Matches.push_back(F.getPair());
}
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads)
+ EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
+
// There's exactly one suitable operator; pick it.
if (Matches.size() == 1) {
Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());
@@ -2702,6 +2717,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return ExprError(Diag(StartLoc, diag::err_delete_operand)
<< Type << Ex.get()->getSourceRange());
} else if (!Pointee->isDependentType()) {
+ // FIXME: This can result in errors if the definition was imported from a
+ // module but is hidden.
if (!RequireCompleteType(StartLoc, Pointee,
diag::warn_delete_incomplete, Ex.get())) {
if (const RecordType *RT = PointeeElem->getAs<RecordType>())
@@ -2712,7 +2729,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (Pointee->isArrayType() && !ArrayForm) {
Diag(StartLoc, diag::warn_delete_array_type)
<< Type << Ex.get()->getSourceRange()
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(StartLoc), "[]");
ArrayForm = true;
}
@@ -2777,7 +2794,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (!OperatorDelete)
// Look for a global declaration.
OperatorDelete = FindUsualDeallocationFunction(
- StartLoc, !RequireCompleteType(StartLoc, Pointee, 0) &&
+ StartLoc, isCompleteType(StartLoc, Pointee) &&
(!ArrayForm || UsualArrayDeleteWantsSize ||
Pointee.isDestructedType()),
DeleteName);
@@ -3103,6 +3120,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
ToType = ToAtomic->getValueType();
}
+ QualType InitialFromType = FromType;
// Perform the first implicit conversion.
switch (SCS.First) {
case ICK_Identity:
@@ -3293,8 +3311,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// We may not have been able to figure out what this member pointer resolved
// to up until this exact point. Attempt to lock-in it's inheritance model.
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- RequireCompleteType(From->getExprLoc(), From->getType(), 0);
- RequireCompleteType(From->getExprLoc(), ToType, 0);
+ (void)isCompleteType(From->getExprLoc(), From->getType());
+ (void)isCompleteType(From->getExprLoc(), ToType);
}
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
@@ -3432,6 +3450,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Function_To_Pointer:
case ICK_Qualification:
case ICK_Num_Conversion_Kinds:
+ case ICK_C_Only_Conversion:
llvm_unreachable("Improper second standard conversion");
}
@@ -3472,6 +3491,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
VK_RValue, nullptr, CCK).get();
}
+ // If this conversion sequence succeeded and involved implicitly converting a
+ // _Nullable type to a _Nonnull one, complain.
+ if (CCK == CCK_ImplicitConversion)
+ diagnoseNullableToNonnullConversion(ToType, InitialFromType,
+ From->getLocStart());
+
return From;
}
@@ -3534,27 +3559,43 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsVolatile:
case UTT_IsSigned:
case UTT_IsUnsigned:
+
+ // This type trait always returns false, checking the type is moot.
+ case UTT_IsInterfaceClass:
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // If T is a non-union class type, T shall be a complete type.
+ case UTT_IsEmpty:
+ case UTT_IsPolymorphic:
+ case UTT_IsAbstract:
+ if (const auto *RD = ArgTy->getAsCXXRecordDecl())
+ if (!RD->isUnion())
+ return !S.RequireCompleteType(
+ Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // If T is a class type, T shall be a complete type.
+ case UTT_IsFinal:
+ case UTT_IsSealed:
+ if (ArgTy->getAsCXXRecordDecl())
+ return !S.RequireCompleteType(
+ Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
return true;
- // C++0x [meta.unary.prop] Table 49 requires the following traits to be
- // applied to a complete type.
+ // C++0x [meta.unary.prop] Table 49 requires the following traits to be
+ // applied to a complete type.
case UTT_IsTrivial:
case UTT_IsTriviallyCopyable:
case UTT_IsStandardLayout:
case UTT_IsPOD:
case UTT_IsLiteral:
- case UTT_IsEmpty:
- case UTT_IsPolymorphic:
- case UTT_IsAbstract:
- case UTT_IsInterfaceClass:
+
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
// Fall-through
- // These traits require a complete type.
- case UTT_IsFinal:
- case UTT_IsSealed:
-
// These trait expressions are designed to help implement predicates in
// [meta.unary.prop] despite not being named the same. They are specified
// by both GCC and the Embarcadero C++ compiler, and require the complete
@@ -3698,39 +3739,36 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
case UTT_IsVolatile:
return T.isVolatileQualified();
case UTT_IsTrivial:
- return T.isTrivialType(Self.Context);
+ return T.isTrivialType(C);
case UTT_IsTriviallyCopyable:
- return T.isTriviallyCopyableType(Self.Context);
+ return T.isTriviallyCopyableType(C);
case UTT_IsStandardLayout:
return T->isStandardLayoutType();
case UTT_IsPOD:
- return T.isPODType(Self.Context);
+ return T.isPODType(C);
case UTT_IsLiteral:
- return T->isLiteralType(Self.Context);
+ return T->isLiteralType(C);
case UTT_IsEmpty:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return !RD->isUnion() && RD->isEmpty();
return false;
case UTT_IsPolymorphic:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isPolymorphic();
+ return !RD->isUnion() && RD->isPolymorphic();
return false;
case UTT_IsAbstract:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isAbstract();
+ return !RD->isUnion() && RD->isAbstract();
return false;
+ // __is_interface_class only returns true when CL is invoked in /CLR mode and
+ // even then only when it is used with the 'interface struct ...' syntax
+ // Clang doesn't support /CLR which makes this type trait moot.
case UTT_IsInterfaceClass:
- if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isInterface();
return false;
case UTT_IsFinal:
- if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->hasAttr<FinalAttr>();
- return false;
case UTT_IsSealed:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- if (FinalAttr *FA = RD->getAttr<FinalAttr>())
- return FA->isSpelledAsSealed();
+ return RD->hasAttr<FinalAttr>();
return false;
case UTT_IsSigned:
return T->isSignedIntegerType();
@@ -3757,7 +3795,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// If __is_pod (type) is true then the trait is true, else if type is
// a cv class or union type (or array thereof) with a trivial default
// constructor ([class.ctor]) then the trait is true, else it is false.
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialDefaultConstructor() &&
@@ -3767,7 +3805,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically this is used as the logic
// behind std::is_trivially_move_constructible (20.9.4.3).
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor();
@@ -3778,7 +3816,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// the trait is true, else if type is a cv class or union type
// with a trivial copy constructor ([class.copy]) then the trait
// is true, else it is false.
- if (T.isPODType(Self.Context) || T->isReferenceType())
+ if (T.isPODType(C) || T->isReferenceType())
return true;
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return RD->hasTrivialCopyConstructor() &&
@@ -3788,7 +3826,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically it is used as the logic
// behind std::is_trivially_move_assignable (20.9.4.3)
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment();
@@ -3808,7 +3846,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
if (T.isConstQualified())
return false;
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return RD->hasTrivialCopyAssignment() &&
@@ -3816,8 +3854,47 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
- // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible.
- // For now, let's fall through.
+ // C++14 [meta.unary.prop]:
+ // For reference types, is_destructible<T>::value is true.
+ if (T->isReferenceType())
+ return true;
+
+ // Objective-C++ ARC: autorelease types don't require destruction.
+ if (T->isObjCLifetimeType() &&
+ T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // For incomplete types and function types, is_destructible<T>::value is
+ // false.
+ if (T->isIncompleteType() || T->isFunctionType())
+ return false;
+
+ // C++14 [meta.unary.prop]:
+ // For object types and given U equal to remove_all_extents_t<T>, if the
+ // expression std::declval<U&>().~U() is well-formed when treated as an
+ // unevaluated operand (Clause 5), then is_destructible<T>::value is true
+ if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) {
+ CXXDestructorDecl *Destructor = Self.LookupDestructor(RD);
+ if (!Destructor)
+ return false;
+ // C++14 [dcl.fct.def.delete]p2:
+ // A program that refers to a deleted function implicitly or
+ // explicitly, other than to declare it, is ill-formed.
+ if (Destructor->isDeleted())
+ return false;
+ if (C.getLangOpts().AccessControl && Destructor->getAccess() != AS_public)
+ return false;
+ if (UTT == UTT_IsNothrowDestructible) {
+ const FunctionProtoType *CPT =
+ Destructor->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT || !CPT->isNothrow(C))
+ return false;
+ }
+ }
+ return true;
+
case UTT_HasTrivialDestructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __is_pod (type) is true or type is a reference type
@@ -3825,7 +3902,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// type (or array thereof) with a trivial destructor
// ([class.dtor]) then the trait is true, else it is
// false.
- if (T.isPODType(Self.Context) || T->isReferenceType())
+ if (T.isPODType(C) || T->isReferenceType())
return true;
// Objective-C++ ARC: autorelease types don't require destruction.
@@ -3849,7 +3926,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
if (T->isReferenceType())
return false;
- if (T.isPODType(Self.Context) || T->isObjCLifetimeType())
+ if (T.isPODType(C) || T->isObjCLifetimeType())
return true;
if (const RecordType *RT = T->getAs<RecordType>())
@@ -3862,7 +3939,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically this is used as the logic
// behind std::is_nothrow_move_assignable (20.9.4.3).
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>())
@@ -3886,15 +3963,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
bool FoundConstructor = false;
unsigned FoundTQs;
- DeclContext::lookup_result R = Self.LookupConstructors(RD);
- for (DeclContext::lookup_iterator Con = R.begin(),
- ConEnd = R.end(); Con != ConEnd; ++Con) {
+ for (const auto *ND : Self.LookupConstructors(RD)) {
// A template constructor is never a copy constructor.
// FIXME: However, it may actually be selected at the actual overload
// resolution point.
- if (isa<FunctionTemplateDecl>(*Con))
+ if (isa<FunctionTemplateDecl>(ND))
continue;
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
if (Constructor->isCopyConstructor(FoundTQs)) {
FoundConstructor = true;
const FunctionProtoType *CPT
@@ -3904,7 +3979,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 1)
+ if (!CPT->isNothrow(C) || CPT->getNumParams() > 1)
return false;
}
}
@@ -3926,13 +4001,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return true;
bool FoundConstructor = false;
- DeclContext::lookup_result R = Self.LookupConstructors(RD);
- for (DeclContext::lookup_iterator Con = R.begin(),
- ConEnd = R.end(); Con != ConEnd; ++Con) {
+ for (const auto *ND : Self.LookupConstructors(RD)) {
// FIXME: In C++0x, a constructor template can be a default constructor.
- if (isa<FunctionTemplateDecl>(*Con))
+ if (isa<FunctionTemplateDecl>(ND))
continue;
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
if (Constructor->isDefaultConstructor()) {
FoundConstructor = true;
const FunctionProtoType *CPT
@@ -3942,7 +4015,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 0)
+ if (!CPT->isNothrow(C) || CPT->getNumParams() > 0)
return false;
}
}
@@ -4023,8 +4096,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// Precondition: T and all types in the parameter pack Args shall be
// complete types, (possibly cv-qualified) void, or arrays of
// unknown bound.
- for (unsigned I = 0, N = Args.size(); I != N; ++I) {
- QualType ArgTy = Args[I]->getType();
+ for (const auto *TSI : Args) {
+ QualType ArgTy = TSI->getType();
if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType())
continue;
@@ -4033,12 +4106,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
return false;
}
- // Make sure the first argument is a complete type.
- if (Args[0]->getType()->isIncompleteType())
+ // Make sure the first argument is not incomplete nor a function type.
+ QualType T = Args[0]->getType();
+ if (T->isIncompleteType() || T->isFunctionType())
return false;
// Make sure the first argument is not an abstract type.
- CXXRecordDecl *RD = Args[0]->getType()->getAsCXXRecordDecl();
+ CXXRecordDecl *RD = T->getAsCXXRecordDecl();
if (RD && RD->isAbstract())
return false;
@@ -4046,13 +4120,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
SmallVector<Expr *, 2> ArgExprs;
ArgExprs.reserve(Args.size() - 1);
for (unsigned I = 1, N = Args.size(); I != N; ++I) {
- QualType T = Args[I]->getType();
- if (T->isObjectType() || T->isFunctionType())
- T = S.Context.getRValueReferenceType(T);
+ QualType ArgTy = Args[I]->getType();
+ if (ArgTy->isObjectType() || ArgTy->isFunctionType())
+ ArgTy = S.Context.getRValueReferenceType(ArgTy);
OpaqueArgExprs.push_back(
- OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
- T.getNonLValueExprType(S.Context),
- Expr::getValueKindForType(T)));
+ OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
+ ArgTy.getNonLValueExprType(S.Context),
+ Expr::getValueKindForType(ArgTy)));
}
for (Expr &E : OpaqueArgExprs)
ArgExprs.push_back(&E);
@@ -4083,7 +4157,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// Under Objective-C ARC, if the destination has non-trivial Objective-C
// lifetime, this is a non-trivial construction.
if (S.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
+ hasNontrivialObjCLifetime(T.getNonReferenceType()))
return false;
// The initialization succeeded; now make sure there are no non-trivial
@@ -4219,8 +4293,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
return LhsT->isVoidType();
// A function definition requires a complete, non-abstract return type.
- if (Self.RequireCompleteType(KeyLoc, RhsT, 0) ||
- Self.RequireNonAbstractType(KeyLoc, RhsT, 0))
+ if (!Self.isCompleteType(KeyLoc, RhsT) || Self.isAbstractType(KeyLoc, RhsT))
return false;
// Compute the result of add_rvalue_reference.
@@ -4506,7 +4579,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
return QualType();
}
- if (!IsDerivedFrom(LHSType, Class)) {
+ if (!IsDerivedFrom(Loc, LHSType, Class)) {
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
<< (int)isIndirect << LHS.get()->getType();
return QualType();
@@ -4634,9 +4707,9 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
const RecordType *FRec = FTy->getAs<RecordType>();
const RecordType *TRec = TTy->getAs<RecordType>();
bool FDerivedFromT = FRec && TRec && FRec != TRec &&
- Self.IsDerivedFrom(FTy, TTy);
- if (FRec && TRec &&
- (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) {
+ Self.IsDerivedFrom(QuestionLoc, FTy, TTy);
+ if (FRec && TRec && (FRec == TRec || FDerivedFromT ||
+ Self.IsDerivedFrom(QuestionLoc, TTy, FTy))) {
// E1 can be converted to match E2 if the class of T2 is the
// same type as, or a base class of, the class of T1, and
// [cv2 > cv1].
@@ -5671,9 +5744,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
//
// This also indicates that we could be parsing a pseudo-destructor-name.
// Note that Objective-C class and object types can be pseudo-destructor
- // expressions or normal member (ivar or property) access expressions.
+ // expressions or normal member (ivar or property) access expressions, and
+ // it's legal for the type to be incomplete if this is a pseudo-destructor
+ // call. We'll do more incomplete-type checks later in the lookup process,
+ // so just skip this check for ObjC types.
if (BaseType->isObjCObjectOrInterfaceType()) {
+ ObjectType = ParsedType::make(BaseType);
MayBePseudoDestructor = true;
+ return Base;
} else if (!BaseType->isRecordType()) {
ObjectType = ParsedType();
MayBePseudoDestructor = true;
@@ -6331,7 +6409,7 @@ static ExprResult attemptRecovery(Sema &SemaRef,
else if (SS && !TC.WillReplaceSpecifier())
NewSS = *SS;
- if (auto *ND = TC.getCorrectionDecl()) {
+ if (auto *ND = TC.getFoundDecl()) {
R.setLookupName(ND->getDeclName());
R.addDecl(ND);
if (ND->isCXXClassMember()) {
@@ -6364,7 +6442,7 @@ static ExprResult attemptRecovery(Sema &SemaRef,
if (MightBeImplicitMember)
return SemaRef.BuildPossibleImplicitMemberExpr(
NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
- /*TemplateArgs*/ nullptr);
+ /*TemplateArgs*/ nullptr, /*S*/ nullptr);
} else if (auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
return SemaRef.LookupInObjCMethod(R, Consumer.getScope(),
Ivar->getIdentifier());
@@ -6452,9 +6530,9 @@ class TransformTypos : public TreeTransform<TransformTypos> {
if (!E)
return nullptr;
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- return DRE->getDecl();
+ return DRE->getFoundDecl();
if (auto *ME = dyn_cast<MemberExpr>(E))
- return ME->getMemberDecl();
+ return ME->getFoundDecl();
// FIXME: Add any other expr types that could be be seen by the delayed typo
// correction TreeTransform for which the corresponding TypoCorrection could
// contain multiple decls.
@@ -6494,6 +6572,8 @@ public:
ExprResult TransformLambdaExpr(LambdaExpr *E) { return Owned(E); }
+ ExprResult TransformBlockExpr(BlockExpr *E) { return Owned(E); }
+
ExprResult Transform(Expr *E) {
ExprResult Res;
while (true) {
@@ -6557,7 +6637,7 @@ public:
// For the first TypoExpr and an uncached TypoExpr, find the next likely
// typo correction and return it.
while (TypoCorrection TC = State.Consumer->getNextCorrection()) {
- if (InitDecl && TC.getCorrectionDecl() == InitDecl)
+ if (InitDecl && TC.getFoundDecl() == InitDecl)
continue;
ExprResult NE = State.RecoveryHandler ?
State.RecoveryHandler(SemaRef, E, TC) :
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index a9f1919e18a8..9c345f8a69a3 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -27,18 +27,15 @@ using namespace clang;
using namespace sema;
typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet;
-static bool BaseIsNotInSet(const CXXRecordDecl *Base, void *BasesPtr) {
- const BaseSet &Bases = *reinterpret_cast<const BaseSet*>(BasesPtr);
- return !Bases.count(Base->getCanonicalDecl());
-}
/// Determines if the given class is provably not derived from all of
/// the prospective base classes.
static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record,
const BaseSet &Bases) {
- void *BasesPtr = const_cast<void*>(reinterpret_cast<const void*>(&Bases));
- return BaseIsNotInSet(Record, BasesPtr) &&
- Record->forallBases(BaseIsNotInSet, BasesPtr);
+ auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) {
+ return !Bases.count(Base->getCanonicalDecl());
+ };
+ return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet);
}
enum IMAKind {
@@ -105,8 +102,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
bool hasNonInstance = false;
bool isField = false;
BaseSet Classes;
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- NamedDecl *D = *I;
+ for (NamedDecl *D : R) {
+ // Look through any using decls.
+ D = D->getUnderlyingDecl();
if (D->isCXXInstanceMember()) {
isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) ||
@@ -114,8 +112,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
Classes.insert(R->getCanonicalDecl());
- }
- else
+ } else
hasNonInstance = true;
}
@@ -237,15 +234,17 @@ ExprResult
Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
- const TemplateArgumentListInfo *TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S) {
switch (ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
- return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true);
+ return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);
case IMA_Mixed:
case IMA_Mixed_Unrelated:
case IMA_Unresolved:
- return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false);
+ return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
+ S);
case IMA_Field_Uneval_Context:
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
@@ -633,6 +632,16 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
DeclarationName Typo = R.getLookupName();
SourceLocation TypoLoc = R.getNameLoc();
+
+ struct QueryState {
+ Sema &SemaRef;
+ DeclarationNameInfo NameInfo;
+ Sema::LookupNameKind LookupKind;
+ Sema::RedeclarationKind Redecl;
+ };
+ QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
+ R.isForRedeclaration() ? Sema::ForRedeclaration
+ : Sema::NotForRedeclaration};
TE = SemaRef.CorrectTypoDelayed(
R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS,
llvm::make_unique<RecordMemberExprValidatorCCC>(RTy),
@@ -651,6 +660,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
}
},
[=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {
+ LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl);
R.clear(); // Ensure there's no decls lingering in the shared state.
R.suppressDiagnostics();
R.setLookupName(TC.getCorrection());
@@ -659,7 +669,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
R.resolveKind();
return SemaRef.BuildMemberReferenceExpr(
BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),
- nullptr, R, nullptr);
+ nullptr, R, nullptr, nullptr);
},
Sema::CTK_ErrorRecovery, DC);
@@ -679,6 +689,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
NamedDecl *FirstQualifierInScope,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
ActOnMemberAccessExtraArgs *ExtraArgs) {
if (BaseType->isDependentType() ||
(SS.isSet() && isDependentScopeSpecifier(SS)))
@@ -725,7 +736,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
return BuildMemberReferenceExpr(Base, BaseType,
OpLoc, IsArrow, SS, TemplateKWLoc,
- FirstQualifierInScope, R, TemplateArgs,
+ FirstQualifierInScope, R, TemplateArgs, S,
false, ExtraArgs);
}
@@ -877,6 +888,18 @@ static MemberExpr *BuildMemberExpr(
return E;
}
+/// \brief Determine if the given scope is within a function-try-block handler.
+static bool IsInFnTryBlockHandler(const Scope *S) {
+ // Walk the scope stack until finding a FnTryCatchScope, or leave the
+ // function scope. If a FnTryCatchScope is found, check whether the TryScope
+ // flag is set. If it is not, it's a function-try-block handler.
+ for (; S != S->getFnParent(); S = S->getParent()) {
+ if (S->getFlags() & Scope::FnTryCatchScope)
+ return (S->getFlags() & Scope::TryScope) != Scope::TryScope;
+ }
+ return false;
+}
+
ExprResult
Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
SourceLocation OpLoc, bool IsArrow,
@@ -885,6 +908,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
NamedDecl *FirstQualifierInScope,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
bool SuppressQualifierCheck,
ActOnMemberAccessExtraArgs *ExtraArgs) {
QualType BaseType = BaseExprType;
@@ -948,6 +972,17 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
if (R.isAmbiguous())
return ExprError();
+ // [except.handle]p10: Referring to any non-static member or base class of an
+ // object in the handler for a function-try-block of a constructor or
+ // destructor for that object results in undefined behavior.
+ const auto *FD = getCurFunctionDecl();
+ if (S && BaseExpr && FD &&
+ (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
+ isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) &&
+ IsInFnTryBlockHandler(S))
+ Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr)
+ << isa<CXXDestructorDecl>(FD);
+
if (R.empty()) {
// Rederive where we looked up.
DeclContext *DC = (SS.isSet()
@@ -1042,16 +1077,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
}
- bool ShouldCheckUse = true;
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
- // Don't diagnose the use of a virtual member function unless it's
- // explicitly qualified.
- if (MD->isVirtual() && !SS.isSet())
- ShouldCheckUse = false;
- }
-
// Check the use of this member.
- if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc))
+ if (DiagnoseUseOfDecl(MemberDecl, MemberLoc))
return ExprError();
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
@@ -1645,7 +1672,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS,
TemplateKWLoc, FirstQualifierInScope,
- NameInfo, TemplateArgs, &ExtraArgs);
+ NameInfo, TemplateArgs, S, &ExtraArgs);
}
static ExprResult
@@ -1718,7 +1745,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
- bool IsKnownInstance) {
+ bool IsKnownInstance, const Scope *S) {
assert(!R.empty() && !R.isAmbiguous());
SourceLocation loc = R.getNameLoc();
@@ -1743,5 +1770,5 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
/*IsArrow*/ true,
SS, TemplateKWLoc,
/*FirstQualifierInScope*/ nullptr,
- R, TemplateArgs);
+ R, TemplateArgs, S);
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 6cd062621951..65f10816924f 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -32,24 +32,21 @@ using namespace sema;
using llvm::makeArrayRef;
ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
- Expr **strings,
- unsigned NumStrings) {
- StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
-
+ ArrayRef<Expr *> Strings) {
// Most ObjC strings are formed out of a single piece. However, we *can*
// have strings formed out of multiple @ strings with multiple pptokens in
// each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one
// StringLiteral for ObjCStringLiteral to hold onto.
- StringLiteral *S = Strings[0];
+ StringLiteral *S = cast<StringLiteral>(Strings[0]);
// If we have a multi-part string, merge it all together.
- if (NumStrings != 1) {
+ if (Strings.size() != 1) {
// Concatenate objc strings.
SmallString<128> StrBuf;
SmallVector<SourceLocation, 8> StrLocs;
- for (unsigned i = 0; i != NumStrings; ++i) {
- S = Strings[i];
+ for (Expr *E : Strings) {
+ S = cast<StringLiteral>(E);
// ObjC strings can't be wide or UTF.
if (!S->isAscii()) {
@@ -168,6 +165,77 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
return true;
}
+/// \brief Maps ObjCLiteralKind to NSClassIdKindKind
+static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind(
+ Sema::ObjCLiteralKind LiteralKind) {
+ switch (LiteralKind) {
+ case Sema::LK_Array:
+ return NSAPI::ClassId_NSArray;
+ case Sema::LK_Dictionary:
+ return NSAPI::ClassId_NSDictionary;
+ case Sema::LK_Numeric:
+ return NSAPI::ClassId_NSNumber;
+ case Sema::LK_String:
+ return NSAPI::ClassId_NSString;
+ case Sema::LK_Boxed:
+ return NSAPI::ClassId_NSValue;
+
+ // there is no corresponding matching
+ // between LK_None/LK_Block and NSClassIdKindKind
+ case Sema::LK_Block:
+ case Sema::LK_None:
+ break;
+ }
+ llvm_unreachable("LiteralKind can't be converted into a ClassKind");
+}
+
+/// \brief Validates ObjCInterfaceDecl availability.
+/// ObjCInterfaceDecl, used to create ObjC literals, should be defined
+/// if clang not in a debugger mode.
+static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
+ SourceLocation Loc,
+ Sema::ObjCLiteralKind LiteralKind) {
+ if (!Decl) {
+ NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind);
+ IdentifierInfo *II = S.NSAPIObj->getNSClassId(Kind);
+ S.Diag(Loc, diag::err_undeclared_objc_literal_class)
+ << II->getName() << LiteralKind;
+ return false;
+ } else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) {
+ S.Diag(Loc, diag::err_undeclared_objc_literal_class)
+ << Decl->getName() << LiteralKind;
+ S.Diag(Decl->getLocation(), diag::note_forward_class);
+ return false;
+ }
+
+ return true;
+}
+
+/// \brief Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
+/// Used to create ObjC literals, such as NSDictionary (@{}),
+/// NSArray (@[]) and Boxed Expressions (@())
+static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S,
+ SourceLocation Loc,
+ Sema::ObjCLiteralKind LiteralKind) {
+ NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind);
+ IdentifierInfo *II = S.NSAPIObj->getNSClassId(ClassKind);
+ NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc,
+ Sema::LookupOrdinaryName);
+ ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (!ID && S.getLangOpts().DebuggerObjCLiteral) {
+ ASTContext &Context = S.Context;
+ TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+ ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II,
+ nullptr, nullptr, SourceLocation());
+ }
+
+ if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) {
+ ID = nullptr;
+ }
+
+ return ID;
+}
+
/// \brief Retrieve the NSNumber factory method that should be used to create
/// an Objective-C literal for the given type.
static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
@@ -197,26 +265,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
// Look up the NSNumber class, if we haven't done so already. It's cached
// in the Sema instance.
if (!S.NSNumberDecl) {
- IdentifierInfo *NSNumberId =
- S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber);
- NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId,
- Loc, Sema::LookupOrdinaryName);
- S.NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ S.NSNumberDecl = LookupObjCInterfaceDeclForLiteral(S, Loc,
+ Sema::LK_Numeric);
if (!S.NSNumberDecl) {
- if (S.getLangOpts().DebuggerObjCLiteral) {
- // Create a stub definition of NSNumber.
- S.NSNumberDecl = ObjCInterfaceDecl::Create(CX,
- CX.getTranslationUnitDecl(),
- SourceLocation(), NSNumberId,
- nullptr, nullptr,
- SourceLocation());
- } else {
- // Otherwise, require a declaration of NSNumber.
- S.Diag(Loc, diag::err_undeclared_nsnumber);
- return nullptr;
- }
- } else if (!S.NSNumberDecl->hasDefinition()) {
- S.Diag(Loc, diag::err_undeclared_nsnumber);
return nullptr;
}
}
@@ -457,6 +508,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
if (RValue.isInvalid()) {
return ExprError();
}
+ SourceLocation Loc = SR.getBegin();
ValueExpr = RValue.get();
QualType ValueType(ValueExpr->getType());
if (const PointerType *PT = ValueType->getAs<PointerType>()) {
@@ -464,29 +516,11 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {
if (!NSStringDecl) {
- IdentifierInfo *NSStringId =
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
- NamedDecl *Decl = LookupSingleName(TUScope, NSStringId,
- SR.getBegin(), LookupOrdinaryName);
- NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl);
+ NSStringDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
+ Sema::LK_String);
if (!NSStringDecl) {
- if (getLangOpts().DebuggerObjCLiteral) {
- // Support boxed expressions in the debugger w/o NSString declaration.
- DeclContext *TU = Context.getTranslationUnitDecl();
- NSStringDecl = ObjCInterfaceDecl::Create(Context, TU,
- SourceLocation(),
- NSStringId,
- nullptr, nullptr,
- SourceLocation());
- } else {
- Diag(SR.getBegin(), diag::err_undeclared_nsstring);
- return ExprError();
- }
- } else if (!NSStringDecl->hasDefinition()) {
- Diag(SR.getBegin(), diag::err_undeclared_nsstring);
return ExprError();
}
- assert(NSStringDecl && "NSStringDecl should not be NULL");
QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl);
NSStringPointer = Context.getObjCObjectPointerType(NSStringObject);
}
@@ -520,7 +554,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = M;
}
- if (!validateBoxingMethod(*this, SR.getBegin(), NSStringDecl,
+ if (!validateBoxingMethod(*this, Loc, NSStringDecl,
stringWithUTF8String, BoxingMethod))
return ExprError();
@@ -563,16 +597,16 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
// FIXME: Do I need to do anything special with BoolTy expressions?
// Look for the appropriate method within NSNumber.
- BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
+ BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType);
BoxedType = NSNumberPointer;
} else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
if (!ET->getDecl()->isComplete()) {
- Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type)
+ Diag(Loc, diag::err_objc_incomplete_boxed_expression_type)
<< ValueType << ValueExpr->getSourceRange();
return ExprError();
}
- BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(),
+ BoxingMethod = getNSNumberFactoryMethod(*this, Loc,
ET->getDecl()->getIntegerType());
BoxedType = NSNumberPointer;
} else if (ValueType->isObjCBoxableRecordType()) {
@@ -582,29 +616,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
// Look up the NSValue class, if we haven't done so already. It's cached
// in the Sema instance.
if (!NSValueDecl) {
- IdentifierInfo *NSValueId =
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSValue);
- NamedDecl *IF = LookupSingleName(TUScope, NSValueId,
- SR.getBegin(), Sema::LookupOrdinaryName);
- NSValueDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ NSValueDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
+ Sema::LK_Boxed);
if (!NSValueDecl) {
- if (getLangOpts().DebuggerObjCLiteral) {
- // Create a stub definition of NSValue.
- DeclContext *TU = Context.getTranslationUnitDecl();
- NSValueDecl = ObjCInterfaceDecl::Create(Context, TU,
- SourceLocation(), NSValueId,
- nullptr, nullptr,
- SourceLocation());
- } else {
- // Otherwise, require a declaration of NSValue.
- Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
- return ExprError();
- }
- } else if (!NSValueDecl->hasDefinition()) {
- Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
return ExprError();
}
-
+
// generate the pointer to NSValue type.
QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);
NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);
@@ -663,7 +680,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = M;
}
- if (!validateBoxingMethod(*this, SR.getBegin(), NSValueDecl,
+ if (!validateBoxingMethod(*this, Loc, NSValueDecl,
ValueWithBytesObjCType, BoxingMethod))
return ExprError();
@@ -671,8 +688,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
}
if (!ValueType.isTriviallyCopyableType(Context)) {
- Diag(SR.getBegin(),
- diag::err_objc_non_trivially_copyable_boxed_expression_type)
+ Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type)
<< ValueType << ValueExpr->getSourceRange();
return ExprError();
}
@@ -682,12 +698,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
}
if (!BoxingMethod) {
- Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type)
+ Diag(Loc, diag::err_objc_illegal_boxed_expression_type)
<< ValueType << ValueExpr->getSourceRange();
return ExprError();
}
- DiagnoseUseOfDecl(BoxingMethod, SR.getBegin());
+ DiagnoseUseOfDecl(BoxingMethod, Loc);
ExprResult ConvertedValueExpr;
if (ValueType->isObjCBoxableRecordType()) {
@@ -746,26 +762,16 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
}
ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
- // Look up the NSArray class, if we haven't done so already.
- if (!NSArrayDecl) {
- NamedDecl *IF = LookupSingleName(TUScope,
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
- SR.getBegin(),
- LookupOrdinaryName);
- NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
- if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral)
- NSArrayDecl = ObjCInterfaceDecl::Create (Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
- nullptr, nullptr, SourceLocation());
+ SourceLocation Loc = SR.getBegin();
+ if (!NSArrayDecl) {
+ NSArrayDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
+ Sema::LK_Array);
if (!NSArrayDecl) {
- Diag(SR.getBegin(), diag::err_undeclared_nsarray);
return ExprError();
}
}
-
+
// Find the arrayWithObjects:count: method, if we haven't done so already.
QualType IdT = Context.getObjCIdType();
if (!ArrayWithObjectsMethod) {
@@ -801,7 +807,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
Method->setMethodParams(Context, Params, None);
}
- if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method))
+ if (!validateBoxingMethod(*this, Loc, NSArrayDecl, Sel, Method))
return ExprError();
// Dig out the type that all elements should be converted to.
@@ -859,28 +865,18 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
ArrayWithObjectsMethod, SR));
}
-ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
- ObjCDictionaryElement *Elements,
- unsigned NumElements) {
- // Look up the NSDictionary class, if we haven't done so already.
- if (!NSDictionaryDecl) {
- NamedDecl *IF = LookupSingleName(TUScope,
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
- SR.getBegin(), LookupOrdinaryName);
- NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
- if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral)
- NSDictionaryDecl = ObjCInterfaceDecl::Create (Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
- nullptr, nullptr, SourceLocation());
+ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
+ MutableArrayRef<ObjCDictionaryElement> Elements) {
+ SourceLocation Loc = SR.getBegin();
+ if (!NSDictionaryDecl) {
+ NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
+ Sema::LK_Dictionary);
if (!NSDictionaryDecl) {
- Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
- return ExprError();
+ return ExprError();
}
}
-
+
// Find the dictionaryWithObjects:forKeys:count: method, if we haven't done
// so already.
QualType IdT = Context.getObjCIdType();
@@ -1007,31 +1003,31 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
// Check that each of the keys and values provided is valid in a collection
// literal, performing conversions as necessary.
bool HasPackExpansions = false;
- for (unsigned I = 0, N = NumElements; I != N; ++I) {
+ for (ObjCDictionaryElement &Element : Elements) {
// Check the key.
- ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key,
+ ExprResult Key = CheckObjCCollectionLiteralElement(*this, Element.Key,
KeyT);
if (Key.isInvalid())
return ExprError();
// Check the value.
ExprResult Value
- = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT);
+ = CheckObjCCollectionLiteralElement(*this, Element.Value, ValueT);
if (Value.isInvalid())
return ExprError();
- Elements[I].Key = Key.get();
- Elements[I].Value = Value.get();
+ Element.Key = Key.get();
+ Element.Value = Value.get();
- if (Elements[I].EllipsisLoc.isInvalid())
+ if (Element.EllipsisLoc.isInvalid())
continue;
- if (!Elements[I].Key->containsUnexpandedParameterPack() &&
- !Elements[I].Value->containsUnexpandedParameterPack()) {
- Diag(Elements[I].EllipsisLoc,
+ if (!Element.Key->containsUnexpandedParameterPack() &&
+ !Element.Value->containsUnexpandedParameterPack()) {
+ Diag(Element.EllipsisLoc,
diag::err_pack_expansion_without_parameter_packs)
- << SourceRange(Elements[I].Key->getLocStart(),
- Elements[I].Value->getLocEnd());
+ << SourceRange(Element.Key->getLocStart(),
+ Element.Value->getLocEnd());
return ExprError();
}
@@ -1043,7 +1039,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
= Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(NSDictionaryDecl));
return MaybeBindToTemporary(ObjCDictionaryLiteral::Create(
- Context, makeArrayRef(Elements, NumElements), HasPackExpansions, Ty,
+ Context, Elements, HasPackExpansions, Ty,
DictionaryWithObjectsMethod, SR));
}
@@ -1092,7 +1088,7 @@ ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
QualType EncodedType = GetTypeFromParser(ty, &TInfo);
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(EncodedType,
- PP.getLocForEndOfToken(LParenLoc));
+ getLocForEndOfToken(LParenLoc));
return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
}
@@ -1657,7 +1653,8 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
// Objective-C pointer type, we may need to extend the lifetime
// of the block object.
if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() &&
- origParamType->isBlockCompatibleObjCPointerType(Context)) {
+ Args[i]->getType()->isBlockPointerType() &&
+ origParamType->isObjCObjectPointerType()) {
ExprResult arg = Args[i];
maybeExtendBlockObject(arg);
Args[i] = arg.get();
@@ -1778,8 +1775,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
diag::err_property_not_found_forward_class,
MemberName, BaseRange))
return ExprError();
-
- // Search for a declared property first.
+
if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
// Check whether we can reference this property.
if (DiagnoseUseOfDecl(PD, MemberLoc))
@@ -2726,6 +2722,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// Try to complete the type. Under ARC, this is a hard error from which
// we don't try to recover.
+ // FIXME: In the non-ARC case, this will still be a hard error if the
+ // definition is found in a module that's not visible.
const ObjCInterfaceDecl *forwardClass = nullptr;
if (RequireCompleteType(Loc, OCIType->getPointeeType(),
getLangOpts().ObjCAutoRefCount
@@ -3397,7 +3395,7 @@ static void addFixitForObjCARCConversion(Sema &S,
DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
BridgeCall));
DiagB.AddFixItHint(FixItHint::CreateInsertion(
- S.PP.getLocForEndOfToken(range.getEnd()),
+ S.getLocForEndOfToken(range.getEnd()),
")"));
}
return;
@@ -3430,7 +3428,7 @@ static void addFixitForObjCARCConversion(Sema &S,
DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
castCode));
DiagB.AddFixItHint(FixItHint::CreateInsertion(
- S.PP.getLocForEndOfToken(range.getEnd()),
+ S.getLocForEndOfToken(range.getEnd()),
")"));
}
}
@@ -3471,7 +3469,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
(castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
if (S.makeUnavailableInSystemHeader(loc,
- "converts between Objective-C and C pointers in -fobjc-arc"))
+ UnavailableAttr::IR_ARCForbiddenConversion))
return;
QualType castExprType = castExpr->getType();
@@ -3498,7 +3496,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
}
// Check whether this could be fixed with a bridge cast.
- SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin());
+ SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin());
SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;
// Bridge from an ARC type to a CF type.
@@ -3901,7 +3899,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
ExpressionString += RelatedClass->getNameAsString();
ExpressionString += " ";
ExpressionString += ClassMethod->getSelector().getAsString();
- SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
+ SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd());
// Provide a fixit: [RelatedClass ClassMethod SrcExpr]
Diag(Loc, diag::err_objc_bridged_related_known_method)
<< SrcType << DestType << ClassMethod->getSelector() << false
@@ -3926,7 +3924,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
// Implicit conversion from ObjC type to CF object is needed.
if (InstanceMethod) {
std::string ExpressionString;
- SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
+ SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd());
if (InstanceMethod->isPropertyAccessor())
if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) {
// fixit: ObjectExpr.propertyname when it is aproperty accessor.
diff --git a/lib/Sema/SemaFixItUtils.cpp b/lib/Sema/SemaFixItUtils.cpp
index 2e327ecf231f..714fbedf09bc 100644
--- a/lib/Sema/SemaFixItUtils.cpp
+++ b/lib/Sema/SemaFixItUtils.cpp
@@ -42,7 +42,7 @@ bool ConversionFixItGenerator::compareTypesSimple(CanQualType From,
const CanQualType FromUnq = From.getUnqualifiedType();
const CanQualType ToUnq = To.getUnqualifiedType();
- if ((FromUnq == ToUnq || (S.IsDerivedFrom(FromUnq, ToUnq)) ) &&
+ if ((FromUnq == ToUnq || (S.IsDerivedFrom(Loc, FromUnq, ToUnq)) ) &&
To.isAtLeastAsQualifiedAs(From))
return true;
return false;
@@ -58,8 +58,8 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr,
const CanQualType FromQTy = S.Context.getCanonicalType(FromTy);
const CanQualType ToQTy = S.Context.getCanonicalType(ToTy);
const SourceLocation Begin = FullExpr->getSourceRange().getBegin();
- const SourceLocation End = S.PP.getLocForEndOfToken(FullExpr->getSourceRange()
- .getEnd());
+ const SourceLocation End = S.getLocForEndOfToken(FullExpr->getSourceRange()
+ .getEnd());
// Strip the implicit casts - those are implied by the compiler, not the
// original source code.
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index adec512693f3..c3a89463dc69 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -443,8 +443,11 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
if (!VerifyOnly) {
SemaRef.Diag(CtorDecl->getLocation(),
diag::warn_invalid_initializer_from_system_header);
- SemaRef.Diag(Entity.getDecl()->getLocation(),
- diag::note_used_in_initialization_here);
+ if (Entity.getKind() == InitializedEntity::EK_Member)
+ SemaRef.Diag(Entity.getDecl()->getLocation(),
+ diag::note_used_in_initialization_here);
+ else if (Entity.getKind() == InitializedEntity::EK_ArrayElement)
+ SemaRef.Diag(Loc, diag::note_used_in_initialization_here);
}
}
}
@@ -802,7 +805,8 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
// Update the structured sub-object initializer so that it's ending
// range corresponds with the end of the last initializer it used.
- if (EndIndex < ParentIList->getNumInits()) {
+ if (EndIndex < ParentIList->getNumInits() &&
+ ParentIList->getInit(EndIndex)) {
SourceLocation EndLoc
= ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
StructuredSubobjectInitList->setRBraceLoc(EndLoc);
@@ -3008,6 +3012,7 @@ bool InitializationSequence::isAmbiguous() const {
case FK_VariableLengthArrayHasInitializer:
case FK_PlaceholderType:
case FK_ExplicitConstructor:
+ case FK_AddressOfUnaddressableFunction:
return false;
case FK_ReferenceInitOverloadFailed:
@@ -3323,7 +3328,7 @@ static bool TryInitializerListConstruction(Sema &S,
if (!S.isStdInitializerList(DestType, &E))
return false;
- if (S.RequireCompleteType(List->getExprLoc(), E, 0)) {
+ if (!S.isCompleteType(List->getExprLoc(), E)) {
Sequence.setIncompleteTypeFailure(E);
return true;
}
@@ -3433,7 +3438,7 @@ static void TryConstructorInitialization(Sema &S,
"IsListInit must come with a single initializer list argument.");
// The type we're constructing needs to be complete.
- if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+ if (!S.isCompleteType(Kind.getLocation(), DestType)) {
Sequence.setIncompleteTypeFailure(DestType);
return;
}
@@ -3674,7 +3679,7 @@ static void TryListInitialization(Sema &S,
}
if (DestType->isRecordType() &&
- S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) {
+ !S.isCompleteType(InitList->getLocStart(), DestType)) {
Sequence.setIncompleteTypeFailure(DestType);
return;
}
@@ -3694,7 +3699,7 @@ static void TryListInitialization(Sema &S,
if (DestType->isRecordType()) {
QualType InitType = InitList->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
- S.IsDerivedFrom(InitType, DestType)) {
+ S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) {
Expr *InitAsExpr = InitList->getInit(0);
TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType,
Sequence, /*InitListSyntax*/ false,
@@ -3728,7 +3733,9 @@ static void TryListInitialization(Sema &S,
// C++11 [dcl.init.list]p3:
// - If T is an aggregate, aggregate initialization is performed.
- if (DestType->isRecordType() && !DestType->isAggregateType()) {
+ if ((DestType->isRecordType() && !DestType->isAggregateType()) ||
+ (S.getLangOpts().CPlusPlus11 &&
+ S.isStdInitializerList(DestType, nullptr))) {
if (S.getLangOpts().CPlusPlus11) {
// - Otherwise, if the initializer list has no elements and T is a
// class type with a default constructor, the object is
@@ -3834,7 +3841,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
const RecordType *T1RecordType = nullptr;
if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
- !S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
+ S.isCompleteType(Kind.getLocation(), T1)) {
// The type we're converting to is a class type. Enumerate its constructors
// to see if there is a suitable conversion.
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
@@ -3870,7 +3877,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
const RecordType *T2RecordType = nullptr;
if ((T2RecordType = T2->getAs<RecordType>()) &&
- !S.RequireCompleteType(Kind.getLocation(), T2, 0)) {
+ S.isCompleteType(Kind.getLocation(), T2)) {
// The type we're converting from is a class type, enumerate its conversion
// functions.
CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
@@ -4455,7 +4462,7 @@ static void TryUserDefinedConversion(Sema &S,
= cast<CXXRecordDecl>(DestRecordType->getDecl());
// Try to complete the type we're converting to.
- if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+ if (S.isCompleteType(Kind.getLocation(), DestType)) {
DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl);
// The container holding the constructors can under certain conditions
// be changed while iterating. To be safe we copy the lookup results
@@ -4501,7 +4508,7 @@ static void TryUserDefinedConversion(Sema &S,
// We can only enumerate the conversion functions for a complete type; if
// the type isn't complete, simply skip this step.
- if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) {
+ if (S.isCompleteType(DeclLoc, SourceType)) {
CXXRecordDecl *SourceRecordDecl
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
@@ -4798,6 +4805,17 @@ InitializationSequence::InitializationSequence(Sema &S,
InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList);
}
+/// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the
+/// address of that function, this returns true. Otherwise, it returns false.
+static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) {
+ auto *DRE = dyn_cast<DeclRefExpr>(E);
+ if (!DRE || !isa<FunctionDecl>(DRE->getDecl()))
+ return false;
+
+ return !S.checkAddressOfFunctionIsAvailable(
+ cast<FunctionDecl>(DRE->getDecl()));
+}
+
void InitializationSequence::InitializeFrom(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4979,7 +4997,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
}
assert(S.getLangOpts().CPlusPlus);
-
+
// - If the destination type is a (possibly cv-qualified) class type:
if (DestType->isRecordType()) {
// - If the initialization is direct-initialization, or if it is
@@ -4989,7 +5007,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Direct ||
(Kind.getKind() == InitializationKind::IK_Copy &&
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
- S.IsDerivedFrom(SourceType, DestType))))
+ S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType))))
TryConstructorInitialization(S, Entity, Kind, Args,
DestType, *this);
// - Otherwise (i.e., for the remaining copy-initialization cases),
@@ -5018,7 +5036,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
bool NeedAtomicConversion = false;
if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) {
if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) ||
- S.IsDerivedFrom(SourceType, Atomic->getValueType())) {
+ S.IsDerivedFrom(Initializer->getLocStart(), SourceType,
+ Atomic->getValueType())) {
DestType = Atomic->getValueType();
NeedAtomicConversion = true;
}
@@ -5076,6 +5095,9 @@ void InitializationSequence::InitializeFrom(Sema &S,
!S.ResolveAddressOfOverloadedFunction(Initializer, DestType,
false, dap))
SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ else if (Initializer->getType()->isFunctionType() &&
+ isExprAnUnaddressableFunction(S, Initializer))
+ SetFailed(InitializationSequence::FK_AddressOfUnaddressableFunction);
else
SetFailed(InitializationSequence::FK_ConversionFailed);
} else {
@@ -6357,7 +6379,7 @@ InitializationSequence::Perform(Sema &S,
CastKind = CK_ConstructorConversion;
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
- S.IsDerivedFrom(SourceType, Class))
+ S.IsDerivedFrom(Loc, SourceType, Class))
IsCopy = true;
CreatedObject = true;
@@ -6596,6 +6618,8 @@ InitializationSequence::Perform(Sema &S,
case SK_CAssignment: {
QualType SourceType = CurInit.get()->getType();
+ // Save off the initial CurInit in case we need to emit a diagnostic
+ ExprResult InitialCurInit = CurInit;
ExprResult Result = CurInit;
Sema::AssignConvertType ConvTy =
S.CheckSingleAssignmentConstraints(Step->Type, Result, true,
@@ -6618,7 +6642,7 @@ InitializationSequence::Perform(Sema &S,
bool Complained;
if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
Step->Type, SourceType,
- CurInit.get(),
+ InitialCurInit.get(),
getAssignmentAction(Entity, true),
&Complained)) {
PrintInitLocationNote(S, Entity);
@@ -6921,6 +6945,13 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
}
+ case FK_AddressOfUnaddressableFunction: {
+ auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(Args[0])->getDecl());
+ S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+ Args[0]->getLocStart());
+ break;
+ }
+
case FK_ReferenceInitOverloadFailed:
case FK_UserConversionOverloadFailed:
switch (FailedOverloadResult) {
@@ -6943,6 +6974,7 @@ bool InitializationSequence::Diagnose(Sema &S,
diag::err_typecheck_nonviable_condition_incomplete,
Args[0]->getType(), Args[0]->getSourceRange()))
S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
+ << (Entity.getKind() == InitializedEntity::EK_Result)
<< Args[0]->getType() << Args[0]->getSourceRange()
<< DestType.getNonReferenceType();
@@ -7043,10 +7075,12 @@ bool InitializationSequence::Diagnose(Sema &S,
SourceRange R;
auto *InitList = dyn_cast<InitListExpr>(Args[0]);
- if (InitList && InitList->getNumInits() == 1)
+ if (InitList && InitList->getNumInits() >= 1) {
R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd());
- else
+ } else {
+ assert(Args.size() > 1 && "Expected multiple initializers!");
R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd());
+ }
R.setBegin(S.getLocForEndOfToken(R.getBegin()));
if (Kind.isCStyleOrFunctionalCast())
@@ -7240,6 +7274,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "array requires initializer list";
break;
+ case FK_AddressOfUnaddressableFunction:
+ OS << "address of unaddressable function was taken";
+ break;
+
case FK_ArrayNeedsInitListOrStringLiteral:
OS << "array requires initializer list or string literal";
break;
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 8220641166b2..884add26e43a 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -226,15 +226,16 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
if (LSI->GLTemplateParameterList)
return LSI->GLTemplateParameterList;
- if (LSI->AutoTemplateParams.size()) {
+ if (!LSI->AutoTemplateParams.empty()) {
SourceRange IntroRange = LSI->IntroducerRange;
SourceLocation LAngleLoc = IntroRange.getBegin();
SourceLocation RAngleLoc = IntroRange.getEnd();
LSI->GLTemplateParameterList = TemplateParameterList::Create(
SemaRef.Context,
/*Template kw loc*/ SourceLocation(), LAngleLoc,
- (NamedDecl **)LSI->AutoTemplateParams.data(),
- LSI->AutoTemplateParams.size(), RAngleLoc);
+ llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(),
+ LSI->AutoTemplateParams.size()),
+ RAngleLoc);
}
return LSI->GLTemplateParameterList;
}
@@ -685,7 +686,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
QualType ReturnType =
(RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
- if (Context.hasSameType(ReturnType, CSI.ReturnType))
+ if (Context.getCanonicalFunctionResultType(ReturnType) ==
+ Context.getCanonicalFunctionResultType(CSI.ReturnType))
continue;
// FIXME: This is a poor diagnostic for ReturnStmts without expressions.
@@ -698,18 +700,11 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
}
}
-QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
- bool ByRef,
- IdentifierInfo *Id,
- Expr *&Init) {
-
- // We do not need to distinguish between direct-list-initialization
- // and copy-list-initialization here, because we will always deduce
- // std::initializer_list<T>, and direct- and copy-list-initialization
- // always behave the same for such a type.
- // FIXME: We should model whether an '=' was present.
- const bool IsDirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init);
-
+QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc,
+ bool ByRef,
+ IdentifierInfo *Id,
+ bool IsDirectInit,
+ Expr *&Init) {
// Create an 'auto' or 'auto&' TypeSourceInfo that we can use to
// deduce against.
QualType DeductType = Context.getAutoDeductType();
@@ -722,50 +717,16 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
}
TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);
- // Are we a non-list direct initialization?
- ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
-
- Expr *DeduceInit = Init;
- // Initializer could be a C++ direct-initializer. Deduction only works if it
- // contains exactly one expression.
- if (CXXDirectInit) {
- if (CXXDirectInit->getNumExprs() == 0) {
- Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_no_expression)
- << DeclarationName(Id) << TSI->getType() << Loc;
- return QualType();
- } else if (CXXDirectInit->getNumExprs() > 1) {
- Diag(CXXDirectInit->getExpr(1)->getLocStart(),
- diag::err_init_capture_multiple_expressions)
- << DeclarationName(Id) << TSI->getType() << Loc;
- return QualType();
- } else {
- DeduceInit = CXXDirectInit->getExpr(0);
- if (isa<InitListExpr>(DeduceInit))
- Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_paren_braces)
- << DeclarationName(Id) << Loc;
- }
- }
-
- // Now deduce against the initialization expression and store the deduced
- // type below.
- QualType DeducedType;
- if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) {
- if (isa<InitListExpr>(Init))
- Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)
- << DeclarationName(Id)
- << (DeduceInit->getType().isNull() ? TSI->getType()
- : DeduceInit->getType())
- << DeduceInit->getSourceRange();
- else
- Diag(Loc, diag::err_init_capture_deduction_failure)
- << DeclarationName(Id) << TSI->getType()
- << (DeduceInit->getType().isNull() ? TSI->getType()
- : DeduceInit->getType())
- << DeduceInit->getSourceRange();
- }
+ // Deduce the type of the init capture.
+ QualType DeducedType = deduceVarTypeFromInitializer(
+ /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI,
+ SourceRange(Loc, Loc), IsDirectInit, Init);
if (DeducedType.isNull())
return QualType();
+ // Are we a non-list direct initialization?
+ ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+
// Perform initialization analysis and ensure any implicit conversions
// (such as lvalue-to-rvalue) are enforced.
InitializedEntity Entity =
@@ -802,9 +763,10 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
return DeducedType;
}
-VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
- QualType InitCaptureType, IdentifierInfo *Id, Expr *Init) {
-
+VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
+ QualType InitCaptureType,
+ IdentifierInfo *Id,
+ unsigned InitStyle, Expr *Init) {
TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType,
Loc);
// Create a dummy variable representing the init-capture. This is not actually
@@ -815,6 +777,8 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
Loc, Id, InitCaptureType, TSI, SC_Auto);
NewVD->setInitCapture(true);
NewVD->setReferenced(true);
+ // FIXME: Pass in a VarDecl::InitializationStyle.
+ NewVD->setInitStyle(static_cast<VarDecl::InitializationStyle>(InitStyle));
NewVD->markUsed(Context);
NewVD->setInit(Init);
return NewVD;
@@ -1013,8 +977,23 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// in this case.
if (C->InitCaptureType.get().isNull())
continue;
- Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
- C->Id, C->Init.get());
+
+ unsigned InitStyle;
+ switch (C->InitKind) {
+ case LambdaCaptureInitKind::NoInit:
+ llvm_unreachable("not an init-capture?");
+ case LambdaCaptureInitKind::CopyInit:
+ InitStyle = VarDecl::CInit;
+ break;
+ case LambdaCaptureInitKind::DirectInit:
+ InitStyle = VarDecl::CallInit;
+ break;
+ case LambdaCaptureInitKind::ListInit:
+ InitStyle = VarDecl::ListInit;
+ break;
+ }
+ Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
+ C->Id, InitStyle, C->Init.get());
// C++1y [expr.prim.lambda]p11:
// An init-capture behaves as if it declares and explicitly
// captures a variable [...] whose declarative region is the
@@ -1022,6 +1001,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
if (Var)
PushOnScopeChains(Var, CurScope, false);
} else {
+ assert(C->InitKind == LambdaCaptureInitKind::NoInit &&
+ "init capture has valid but null init?");
+
// C++11 [expr.prim.lambda]p8:
// If a lambda-capture includes a capture-default that is &, the
// identifiers in the lambda-capture shall not be preceded by &.
@@ -1160,6 +1142,12 @@ static void addFunctionPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
+ // This conversion is explicitly disabled if the lambda's function has
+ // pass_object_size attributes on any of its parameters.
+ if (std::any_of(CallOperator->param_begin(), CallOperator->param_end(),
+ std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>)))
+ return;
+
// Add the conversion to function pointer.
const FunctionProtoType *CallOpProto =
CallOperator->getType()->getAs<FunctionProtoType>();
@@ -1700,8 +1688,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
SC_None);
BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false,
/*Nested=*/false, /*Copy=*/Init.get());
- Block->setCaptures(Context, &Capture, &Capture + 1,
- /*CapturesCXXThis=*/false);
+ Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false);
// Add a fake function body to the block. IR generation is responsible
// for filling in the actual body, which cannot be expressed as an AST.
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 2e7f89191580..481ae6cd55b1 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -11,6 +11,7 @@
// Objective-C++.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
@@ -153,7 +154,7 @@ namespace {
// by its using directives, transitively) as if they appeared in
// the given effective context.
void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
- SmallVector<DeclContext*,4> queue;
+ SmallVector<DeclContext*, 4> queue;
while (true) {
for (auto UD : DC->using_directives()) {
DeclContext *NS = UD->getNominatedNamespace();
@@ -204,7 +205,7 @@ namespace {
UnqualUsingEntry::Comparator()));
}
};
-}
+} // end anonymous namespace
// Retrieve the set of identifier namespaces that correspond to a
// specific kind of name lookup.
@@ -354,13 +355,114 @@ static DeclContext *getContextForScopeMatching(Decl *D) {
return D->getDeclContext()->getRedeclContext();
}
+/// \brief Determine whether \p D is a better lookup result than \p Existing,
+/// given that they declare the same entity.
+static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
+ NamedDecl *D, NamedDecl *Existing) {
+ // When looking up redeclarations of a using declaration, prefer a using
+ // shadow declaration over any other declaration of the same entity.
+ if (Kind == Sema::LookupUsingDeclName && isa<UsingShadowDecl>(D) &&
+ !isa<UsingShadowDecl>(Existing))
+ return true;
+
+ auto *DUnderlying = D->getUnderlyingDecl();
+ auto *EUnderlying = Existing->getUnderlyingDecl();
+
+ // If they have different underlying declarations, prefer a typedef over the
+ // original type (this happens when two type declarations denote the same
+ // type), per a generous reading of C++ [dcl.typedef]p3 and p4. The typedef
+ // might carry additional semantic information, such as an alignment override.
+ // However, per C++ [dcl.typedef]p5, when looking up a tag name, prefer a tag
+ // declaration over a typedef.
+ if (DUnderlying->getCanonicalDecl() != EUnderlying->getCanonicalDecl()) {
+ assert(isa<TypeDecl>(DUnderlying) && isa<TypeDecl>(EUnderlying));
+ bool HaveTag = isa<TagDecl>(EUnderlying);
+ bool WantTag = Kind == Sema::LookupTagName;
+ return HaveTag != WantTag;
+ }
+
+ // Pick the function with more default arguments.
+ // FIXME: In the presence of ambiguous default arguments, we should keep both,
+ // so we can diagnose the ambiguity if the default argument is needed.
+ // See C++ [over.match.best]p3.
+ if (auto *DFD = dyn_cast<FunctionDecl>(DUnderlying)) {
+ auto *EFD = cast<FunctionDecl>(EUnderlying);
+ unsigned DMin = DFD->getMinRequiredArguments();
+ unsigned EMin = EFD->getMinRequiredArguments();
+ // If D has more default arguments, it is preferred.
+ if (DMin != EMin)
+ return DMin < EMin;
+ // FIXME: When we track visibility for default function arguments, check
+ // that we pick the declaration with more visible default arguments.
+ }
+
+ // Pick the template with more default template arguments.
+ if (auto *DTD = dyn_cast<TemplateDecl>(DUnderlying)) {
+ auto *ETD = cast<TemplateDecl>(EUnderlying);
+ unsigned DMin = DTD->getTemplateParameters()->getMinRequiredArguments();
+ unsigned EMin = ETD->getTemplateParameters()->getMinRequiredArguments();
+ // If D has more default arguments, it is preferred. Note that default
+ // arguments (and their visibility) is monotonically increasing across the
+ // redeclaration chain, so this is a quick proxy for "is more recent".
+ if (DMin != EMin)
+ return DMin < EMin;
+ // If D has more *visible* default arguments, it is preferred. Note, an
+ // earlier default argument being visible does not imply that a later
+ // default argument is visible, so we can't just check the first one.
+ for (unsigned I = DMin, N = DTD->getTemplateParameters()->size();
+ I != N; ++I) {
+ if (!S.hasVisibleDefaultArgument(
+ ETD->getTemplateParameters()->getParam(I)) &&
+ S.hasVisibleDefaultArgument(
+ DTD->getTemplateParameters()->getParam(I)))
+ return true;
+ }
+ }
+
+ // For most kinds of declaration, it doesn't really matter which one we pick.
+ if (!isa<FunctionDecl>(DUnderlying) && !isa<VarDecl>(DUnderlying)) {
+ // If the existing declaration is hidden, prefer the new one. Otherwise,
+ // keep what we've got.
+ return !S.isVisible(Existing);
+ }
+
+ // Pick the newer declaration; it might have a more precise type.
+ for (Decl *Prev = DUnderlying->getPreviousDecl(); Prev;
+ Prev = Prev->getPreviousDecl())
+ if (Prev == EUnderlying)
+ return true;
+ return false;
+
+ // If the existing declaration is hidden, prefer the new one. Otherwise,
+ // keep what we've got.
+ return !S.isVisible(Existing);
+}
+
+/// Determine whether \p D can hide a tag declaration.
+static bool canHideTag(NamedDecl *D) {
+ // C++ [basic.scope.declarative]p4:
+ // Given a set of declarations in a single declarative region [...]
+ // exactly one declaration shall declare a class name or enumeration name
+ // that is not a typedef name and the other declarations shall all refer to
+ // the same variable or enumerator, or all refer to functions and function
+ // templates; in this case the class name or enumeration name is hidden.
+ // C++ [basic.scope.hiding]p2:
+ // A class name or enumeration name can be hidden by the name of a
+ // variable, data member, function, or enumerator declared in the same
+ // scope.
+ D = D->getUnderlyingDecl();
+ return isa<VarDecl>(D) || isa<EnumConstantDecl>(D) || isa<FunctionDecl>(D) ||
+ isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D);
+}
+
/// Resolves the result kind of this lookup.
void LookupResult::resolveKind() {
unsigned N = Decls.size();
// Fast case: no possible ambiguity.
if (N == 0) {
- assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation);
+ assert(ResultKind == NotFound ||
+ ResultKind == NotFoundInCurrentInstantiation);
return;
}
@@ -378,12 +480,15 @@ void LookupResult::resolveKind() {
// Don't do any extra resolution if we've already resolved as ambiguous.
if (ResultKind == Ambiguous) return;
- llvm::SmallPtrSet<NamedDecl*, 16> Unique;
- llvm::SmallPtrSet<QualType, 16> UniqueTypes;
+ llvm::SmallDenseMap<NamedDecl*, unsigned, 16> Unique;
+ llvm::SmallDenseMap<QualType, unsigned, 16> UniqueTypes;
bool Ambiguous = false;
- bool HasTag = false, HasFunction = false, HasNonFunction = false;
+ bool HasTag = false, HasFunction = false;
bool HasFunctionTemplate = false, HasUnresolved = false;
+ NamedDecl *HasNonFunction = nullptr;
+
+ llvm::SmallVector<NamedDecl*, 4> EquivalentNonFunctions;
unsigned UniqueTagIndex = 0;
@@ -393,34 +498,43 @@ void LookupResult::resolveKind() {
D = cast<NamedDecl>(D->getCanonicalDecl());
// Ignore an invalid declaration unless it's the only one left.
- if (D->isInvalidDecl() && I < N-1) {
+ if (D->isInvalidDecl() && !(I == 0 && N == 1)) {
Decls[I] = Decls[--N];
continue;
}
+ llvm::Optional<unsigned> ExistingI;
+
// Redeclarations of types via typedef can occur both within a scope
// and, through using declarations and directives, across scopes. There is
// no ambiguity if they all refer to the same type, so unique based on the
// canonical type.
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
- if (!TD->getDeclContext()->isRecord()) {
- QualType T = getSema().Context.getTypeDeclType(TD);
- if (!UniqueTypes.insert(getSema().Context.getCanonicalType(T)).second) {
- // The type is not unique; pull something off the back and continue
- // at this index.
- Decls[I] = Decls[--N];
- continue;
- }
+ QualType T = getSema().Context.getTypeDeclType(TD);
+ auto UniqueResult = UniqueTypes.insert(
+ std::make_pair(getSema().Context.getCanonicalType(T), I));
+ if (!UniqueResult.second) {
+ // The type is not unique.
+ ExistingI = UniqueResult.first->second;
+ }
+ }
+
+ // For non-type declarations, check for a prior lookup result naming this
+ // canonical declaration.
+ if (!ExistingI) {
+ auto UniqueResult = Unique.insert(std::make_pair(D, I));
+ if (!UniqueResult.second) {
+ // We've seen this entity before.
+ ExistingI = UniqueResult.first->second;
}
}
- if (!Unique.insert(D).second) {
- // If it's not unique, pull something off the back (and
- // continue at this index).
- // FIXME: This is wrong. We need to take the more recent declaration in
- // order to get the right type, default arguments, etc. We also need to
- // prefer visible declarations to hidden ones (for redeclaration lookup
- // in modules builds).
+ if (ExistingI) {
+ // This is not a unique lookup result. Pick one of the results and
+ // discard the other.
+ if (isPreferredLookupResult(getSema(), getLookupKind(), Decls[I],
+ Decls[*ExistingI]))
+ Decls[*ExistingI] = Decls[I];
Decls[I] = Decls[--N];
continue;
}
@@ -440,9 +554,21 @@ void LookupResult::resolveKind() {
} else if (isa<FunctionDecl>(D)) {
HasFunction = true;
} else {
- if (HasNonFunction)
+ if (HasNonFunction) {
+ // If we're about to create an ambiguity between two declarations that
+ // are equivalent, but one is an internal linkage declaration from one
+ // module and the other is an internal linkage declaration from another
+ // module, just skip it.
+ if (getSema().isEquivalentInternalLinkageDeclaration(HasNonFunction,
+ D)) {
+ EquivalentNonFunctions.push_back(D);
+ Decls[I] = Decls[--N];
+ continue;
+ }
+
Ambiguous = true;
- HasNonFunction = true;
+ }
+ HasNonFunction = D;
}
I++;
}
@@ -456,15 +582,24 @@ void LookupResult::resolveKind() {
// wherever the object, function, or enumerator name is visible.
// But it's still an error if there are distinct tag types found,
// even if they're not visible. (ref?)
- if (HideTags && HasTag && !Ambiguous &&
+ if (N > 1 && HideTags && HasTag && !Ambiguous &&
(HasFunction || HasNonFunction || HasUnresolved)) {
- if (getContextForScopeMatching(Decls[UniqueTagIndex])->Equals(
- getContextForScopeMatching(Decls[UniqueTagIndex ? 0 : N - 1])))
+ NamedDecl *OtherDecl = Decls[UniqueTagIndex ? 0 : N - 1];
+ if (isa<TagDecl>(Decls[UniqueTagIndex]->getUnderlyingDecl()) &&
+ getContextForScopeMatching(Decls[UniqueTagIndex])->Equals(
+ getContextForScopeMatching(OtherDecl)) &&
+ canHideTag(OtherDecl))
Decls[UniqueTagIndex] = Decls[--N];
else
Ambiguous = true;
}
+ // FIXME: This diagnostic should really be delayed until we're done with
+ // the lookup result, in case the ambiguity is resolved by the caller.
+ if (!EquivalentNonFunctions.empty() && !Ambiguous)
+ getSema().diagnoseEquivalentInternalLinkageDeclarations(
+ getNameLoc(), HasNonFunction, EquivalentNonFunctions);
+
Decls.set_size(N);
if (HasNonFunction && (HasFunction || HasUnresolved))
@@ -534,6 +669,11 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
R.addDecl(S.getASTContext().getFloat128StubType());
return true;
}
+ if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName &&
+ II == S.getASTContext().getMakeIntegerSeqName()) {
+ R.addDecl(S.getASTContext().getMakeIntegerSeqDecl());
+ return true;
+ }
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID()) {
@@ -875,7 +1015,7 @@ struct FindLocalExternScope {
LookupResult &R;
bool OldFindLocalExtern;
};
-}
+} // end anonymous namespace
bool Sema::CppLookupName(LookupResult &R, Scope *S) {
assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup");
@@ -1333,22 +1473,22 @@ bool Sema::hasVisibleDefaultArgument(const NamedDecl *D,
/// your module can see, including those later on in your module).
bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
assert(D->isHidden() && "should not call this: not in slow case");
- Module *DeclModule = SemaRef.getOwningModule(D);
- if (!DeclModule) {
- // getOwningModule() may have decided the declaration should not be hidden.
- assert(!D->isHidden() && "hidden decl not from a module");
- return true;
- }
-
- // If the owning module is visible, and the decl is not module private,
- // then the decl is visible too. (Module private is ignored within the same
- // top-level module.)
- if (!D->isFromASTFile() || !D->isModulePrivate()) {
- if (SemaRef.isModuleVisible(DeclModule))
+ Module *DeclModule = nullptr;
+
+ if (SemaRef.getLangOpts().ModulesLocalVisibility) {
+ DeclModule = SemaRef.getOwningModule(D);
+ if (!DeclModule) {
+ // getOwningModule() may have decided the declaration should not be hidden.
+ assert(!D->isHidden() && "hidden decl not from a module");
return true;
- // Also check merged definitions.
- if (SemaRef.getLangOpts().ModulesLocalVisibility &&
- SemaRef.hasVisibleMergedDefinition(D))
+ }
+
+ // If the owning module is visible, and the decl is not module private,
+ // then the decl is visible too. (Module private is ignored within the same
+ // top-level module.)
+ if ((!D->isFromASTFile() || !D->isModulePrivate()) &&
+ (SemaRef.isModuleVisible(DeclModule) ||
+ SemaRef.hasVisibleMergedDefinition(D)))
return true;
}
@@ -1380,6 +1520,11 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
if (LookupModules.empty())
return false;
+ if (!DeclModule) {
+ DeclModule = SemaRef.getOwningModule(D);
+ assert(DeclModule && "hidden decl not from a module");
+ }
+
// If our lookup set contains the decl's module, it's visible.
if (LookupModules.count(DeclModule))
return true;
@@ -1390,18 +1535,22 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
// Check whether DeclModule is transitively exported to an import of
// the lookup set.
- for (llvm::DenseSet<Module *>::iterator I = LookupModules.begin(),
- E = LookupModules.end();
- I != E; ++I)
- if ((*I)->isModuleVisible(DeclModule))
- return true;
- return false;
+ return std::any_of(LookupModules.begin(), LookupModules.end(),
+ [&](Module *M) { return M->isModuleVisible(DeclModule); });
}
bool Sema::isVisibleSlow(const NamedDecl *D) {
return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D));
}
+bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
+ for (auto *D : R) {
+ if (isVisible(D))
+ return true;
+ }
+ return New->isExternallyVisible();
+}
+
/// \brief Retrieve the visible declaration corresponding to D, if any.
///
/// This routine determines whether the declaration D is visible in the current
@@ -1679,12 +1828,10 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
/// \brief Callback that looks for any member of a class with the given name.
static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *Name) {
+ CXXBasePath &Path, DeclarationName Name) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- Path.Decls = BaseRecord->lookup(N);
+ Path.Decls = BaseRecord->lookup(Name);
return !Path.Decls.empty();
}
@@ -1756,7 +1903,18 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
cast<TagDecl>(LookupCtx)->isBeingDefined()) &&
"Declaration context must already be complete!");
- // Perform qualified name lookup into the LookupCtx.
+ struct QualifiedLookupInScope {
+ bool oldVal;
+ DeclContext *Context;
+ // Set flag in DeclContext informing debugger that we're looking for qualified name
+ QualifiedLookupInScope(DeclContext *ctx) : Context(ctx) {
+ oldVal = ctx->setUseQualifiedLookup();
+ }
+ ~QualifiedLookupInScope() {
+ Context->setUseQualifiedLookup(oldVal);
+ }
+ } QL(LookupCtx);
+
if (LookupDirect(*this, R, LookupCtx)) {
R.resolveKind();
if (isa<CXXRecordDecl>(LookupCtx))
@@ -1802,7 +1960,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
Paths.setOrigin(LookupRec);
// Look for this member in our base classes
- CXXRecordDecl::BaseMatchesCallback *BaseCallback = nullptr;
+ bool (*BaseCallback)(const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
+ DeclarationName Name) = nullptr;
switch (R.getLookupKind()) {
case LookupObjCImplicitSelfParam:
case LookupOrdinaryName:
@@ -1835,8 +1994,12 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
break;
}
- if (!LookupRec->lookupInBases(BaseCallback,
- R.getLookupName().getAsOpaquePtr(), Paths))
+ DeclarationName Name = R.getLookupName();
+ if (!LookupRec->lookupInBases(
+ [=](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return BaseCallback(Specifier, Path, Name);
+ },
+ Paths))
return false;
R.setNamingClass(LookupRec);
@@ -2013,17 +2176,30 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
///
/// @returns True if any decls were found (but possibly ambiguous)
bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) {
+ // The access-control rules we use here are essentially the rules for
+ // doing a lookup in Class that just magically skipped the direct
+ // members of Class itself. That is, the naming class is Class, and the
+ // access includes the access of the base.
for (const auto &BaseSpec : Class->bases()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(
BaseSpec.getType()->castAs<RecordType>()->getDecl());
LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind());
Result.setBaseObjectType(Context.getRecordType(Class));
LookupQualifiedName(Result, RD);
- for (auto *Decl : Result)
- R.addDecl(Decl);
+
+ // Copy the lookup results into the target, merging the base's access into
+ // the path access.
+ for (auto I = Result.begin(), E = Result.end(); I != E; ++I) {
+ R.addDecl(I.getDecl(),
+ CXXRecordDecl::MergeAccess(BaseSpec.getAccessSpecifier(),
+ I.getAccess()));
+ }
+
+ Result.suppressDiagnostics();
}
R.resolveKind();
+ R.setNamingClass(Class);
return !R.empty();
}
@@ -2075,7 +2251,7 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
case LookupResult::AmbiguousTagHiding: {
Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange;
- llvm::SmallPtrSet<NamedDecl*,8> TagDecls;
+ llvm::SmallPtrSet<NamedDecl*, 8> TagDecls;
for (auto *D : Result)
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
@@ -2121,7 +2297,7 @@ namespace {
Sema::AssociatedClassSet &Classes;
SourceLocation InstantiationLoc;
};
-}
+} // end anonymous namespace
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T);
@@ -2252,7 +2428,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
}
// Only recurse into base classes for complete types.
- if (!Class->hasDefinition())
+ if (!Result.S.isCompleteType(Result.InstantiationLoc,
+ Result.S.Context.getRecordType(Class)))
return;
// Add direct and indirect base classes along with their associated
@@ -2345,10 +2522,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
// classes. Its associated namespaces are the namespaces in
// which its associated classes are defined.
case Type::Record: {
- Result.S.RequireCompleteType(Result.InstantiationLoc, QualType(T, 0),
- /*no diagnostic*/ 0);
- CXXRecordDecl *Class
- = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
+ CXXRecordDecl *Class =
+ cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
addAssociatedClassesAndNamespaces(Result, Class);
break;
}
@@ -3032,7 +3207,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) {
DeclContext *LexDC = DI->getLexicalDeclContext();
if (isa<CXXRecordDecl>(LexDC) &&
- AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) {
+ AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)) &&
+ isVisible(cast<NamedDecl>(DI))) {
DeclaredInAssociatedClass = true;
break;
}
@@ -3129,9 +3305,6 @@ public:
} // end anonymous namespace
NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
- // Look through using declarations.
- ND = ND->getUnderlyingDecl();
-
unsigned IDNS = ND->getIdentifierNamespace();
std::list<ShadowMap>::reverse_iterator SM = ShadowMaps.rbegin();
for (std::list<ShadowMap>::reverse_iterator SMEnd = ShadowMaps.rend();
@@ -3704,7 +3877,12 @@ void TypoCorrectionConsumer::addNamespaces(
if (const Type *T = NNS->getAsType())
SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization;
}
- for (const auto *TI : SemaRef.getASTContext().types()) {
+ // Do not transform this into an iterator-based loop. The loop body can
+ // trigger the creation of further types (through lazy deserialization) and
+ // invalide iterators into this list.
+ auto &Types = SemaRef.getASTContext().getTypes();
+ for (unsigned I = 0; I != Types.size(); ++I) {
+ const auto *TI = Types[I];
if (CXXRecordDecl *CD = TI->getAsCXXRecordDecl()) {
CD = CD->getCanonicalDecl();
if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() &&
@@ -3805,7 +3983,8 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
// current correction candidate is the name of that class, then skip
// it as it is unlikely a qualified version of the class' constructor
// is an appropriate correction.
- if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() : 0) {
+ if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() :
+ nullptr) {
if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
continue;
}
@@ -4540,7 +4719,7 @@ void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
if (isKeyword())
CorrectionDecls.clear();
- CorrectionDecls.push_back(CDecl->getUnderlyingDecl());
+ CorrectionDecls.push_back(CDecl);
if (!CorrectionName)
CorrectionName = CDecl->getDeclName();
@@ -4769,7 +4948,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
// Maybe we're just missing a module import.
if (Correction.requiresImport()) {
- NamedDecl *Decl = Correction.getCorrectionDecl();
+ NamedDecl *Decl = Correction.getFoundDecl();
assert(Decl && "import required but no declaration to import");
diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl,
@@ -4781,7 +4960,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
<< CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint());
NamedDecl *ChosenDecl =
- Correction.isKeyword() ? nullptr : Correction.getCorrectionDecl();
+ Correction.isKeyword() ? nullptr : Correction.getFoundDecl();
if (PrevNote.getDiagID() && ChosenDecl)
Diag(ChosenDecl->getLocation(), PrevNote)
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index f139c83c734b..1cb84e448067 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -61,8 +61,10 @@ static Qualifiers::ObjCLifetime getImpliedARCOwnership(
return Qualifiers::OCL_None;
}
-/// Check the internal consistency of a property declaration.
-static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
+/// Check the internal consistency of a property declaration with
+/// an explicit ownership qualifier.
+static void checkPropertyDeclWithOwnership(Sema &S,
+ ObjCPropertyDecl *property) {
if (property->isInvalidDecl()) return;
ObjCPropertyDecl::PropertyAttributeKind propertyKind
@@ -70,8 +72,7 @@ static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
Qualifiers::ObjCLifetime propertyLifetime
= property->getType().getObjCLifetime();
- // Nothing to do if we don't have a lifetime.
- if (propertyLifetime == Qualifiers::OCL_None) return;
+ assert(propertyLifetime != Qualifiers::OCL_None);
Qualifiers::ObjCLifetime expectedLifetime
= getImpliedARCOwnership(propertyKind, property->getType());
@@ -127,32 +128,71 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
CheckPropertyAgainstProtocol(S, Prop, P, Known);
}
+static unsigned deducePropertyOwnershipFromType(Sema &S, QualType T) {
+ // In GC mode, just look for the __weak qualifier.
+ if (S.getLangOpts().getGC() != LangOptions::NonGC) {
+ if (T.isObjCGCWeak()) return ObjCDeclSpec::DQ_PR_weak;
+
+ // In ARC/MRC, look for an explicit ownership qualifier.
+ // For some reason, this only applies to __weak.
+ } else if (auto ownership = T.getObjCLifetime()) {
+ switch (ownership) {
+ case Qualifiers::OCL_Weak:
+ return ObjCDeclSpec::DQ_PR_weak;
+ case Qualifiers::OCL_Strong:
+ return ObjCDeclSpec::DQ_PR_strong;
+ case Qualifiers::OCL_ExplicitNone:
+ return ObjCDeclSpec::DQ_PR_unsafe_unretained;
+ case Qualifiers::OCL_Autoreleasing:
+ case Qualifiers::OCL_None:
+ return 0;
+ }
+ llvm_unreachable("bad qualifier");
+ }
+
+ return 0;
+}
+
+static const unsigned OwnershipMask =
+ (ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_copy |
+ ObjCPropertyDecl::OBJC_PR_weak |
+ ObjCPropertyDecl::OBJC_PR_strong |
+ ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
+
+static unsigned getOwnershipRule(unsigned attr) {
+ unsigned result = attr & OwnershipMask;
+
+ // From an ownership perspective, assign and unsafe_unretained are
+ // identical; make sure one also implies the other.
+ if (result & (ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_unsafe_unretained)) {
+ result |= ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
+ }
+
+ return result;
+}
+
Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
SourceLocation LParenLoc,
FieldDeclarator &FD,
ObjCDeclSpec &ODS,
Selector GetterSel,
Selector SetterSel,
- bool *isOverridingProperty,
tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC) {
unsigned Attributes = ODS.getPropertyAttributes();
FD.D.setObjCWeakProperty((Attributes & ObjCDeclSpec::DQ_PR_weak) != 0);
TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
QualType T = TSI->getType();
- Attributes |= deduceWeakPropertyFromType(T);
+ if (!getOwnershipRule(Attributes)) {
+ Attributes |= deducePropertyOwnershipFromType(*this, T);
+ }
bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
// default is readwrite!
!(Attributes & ObjCDeclSpec::DQ_PR_readonly));
- // property is defaulted to 'assign' if it is readwrite and is
- // not retain or copy
- bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
- (isReadWrite &&
- !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
- !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
- !(Attributes & ObjCDeclSpec::DQ_PR_copy) &&
- !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) &&
- !(Attributes & ObjCDeclSpec::DQ_PR_weak)));
// Proceed with constructing the ObjCPropertyDecls.
ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
@@ -161,11 +201,10 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
if (CDecl->IsClassExtension()) {
Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
FD, GetterSel, SetterSel,
- isAssign, isReadWrite,
+ isReadWrite,
Attributes,
ODS.getPropertyAttributes(),
- isOverridingProperty, T, TSI,
- MethodImplKind);
+ T, TSI, MethodImplKind);
if (!Res)
return nullptr;
}
@@ -173,7 +212,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
if (!Res) {
Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
- GetterSel, SetterSel, isAssign, isReadWrite,
+ GetterSel, SetterSel, isReadWrite,
Attributes, ODS.getPropertyAttributes(),
T, TSI, MethodImplKind);
if (lexicalDC)
@@ -181,12 +220,13 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
}
// Validate the attributes on the @property.
- CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
+ CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
(isa<ObjCInterfaceDecl>(ClassDecl) ||
isa<ObjCProtocolDecl>(ClassDecl)));
- if (getLangOpts().ObjCAutoRefCount)
- checkARCPropertyDecl(*this, Res);
+ // Check consistency if the type has explicit ownership qualification.
+ if (Res->getType().getObjCLifetime())
+ checkPropertyDeclWithOwnership(*this, Res);
llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos;
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
@@ -220,8 +260,12 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
}
}
} else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
- for (auto *P : Cat->protocols())
- CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
+ // We don't check if class extension. Because properties in class extension
+ // are meant to override some of the attributes and checking has already done
+ // when property in class extension is constructed.
+ if (!Cat->IsClassExtension())
+ for (auto *P : Cat->protocols())
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
} else {
ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
for (auto *P : Proto->protocols())
@@ -293,13 +337,73 @@ static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
}
-static unsigned getOwnershipRule(unsigned attr) {
- return attr & (ObjCPropertyDecl::OBJC_PR_assign |
- ObjCPropertyDecl::OBJC_PR_retain |
- ObjCPropertyDecl::OBJC_PR_copy |
- ObjCPropertyDecl::OBJC_PR_weak |
- ObjCPropertyDecl::OBJC_PR_strong |
- ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
+/// Check for a mismatch in the atomicity of the given properties.
+static void checkAtomicPropertyMismatch(Sema &S,
+ ObjCPropertyDecl *OldProperty,
+ ObjCPropertyDecl *NewProperty,
+ bool PropagateAtomicity) {
+ // If the atomicity of both matches, we're done.
+ bool OldIsAtomic =
+ (OldProperty->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ == 0;
+ bool NewIsAtomic =
+ (NewProperty->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ == 0;
+ if (OldIsAtomic == NewIsAtomic) return;
+
+ // Determine whether the given property is readonly and implicitly
+ // atomic.
+ auto isImplicitlyReadonlyAtomic = [](ObjCPropertyDecl *Property) -> bool {
+ // Is it readonly?
+ auto Attrs = Property->getPropertyAttributes();
+ if ((Attrs & ObjCPropertyDecl::OBJC_PR_readonly) == 0) return false;
+
+ // Is it nonatomic?
+ if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) return false;
+
+ // Was 'atomic' specified directly?
+ if (Property->getPropertyAttributesAsWritten() &
+ ObjCPropertyDecl::OBJC_PR_atomic)
+ return false;
+
+ return true;
+ };
+
+ // If we're allowed to propagate atomicity, and the new property did
+ // not specify atomicity at all, propagate.
+ const unsigned AtomicityMask =
+ (ObjCPropertyDecl::OBJC_PR_atomic | ObjCPropertyDecl::OBJC_PR_nonatomic);
+ if (PropagateAtomicity &&
+ ((NewProperty->getPropertyAttributesAsWritten() & AtomicityMask) == 0)) {
+ unsigned Attrs = NewProperty->getPropertyAttributes();
+ Attrs = Attrs & ~AtomicityMask;
+ if (OldIsAtomic)
+ Attrs |= ObjCPropertyDecl::OBJC_PR_atomic;
+ else
+ Attrs |= ObjCPropertyDecl::OBJC_PR_nonatomic;
+
+ NewProperty->overwritePropertyAttributes(Attrs);
+ return;
+ }
+
+ // One of the properties is atomic; if it's a readonly property, and
+ // 'atomic' wasn't explicitly specified, we're okay.
+ if ((OldIsAtomic && isImplicitlyReadonlyAtomic(OldProperty)) ||
+ (NewIsAtomic && isImplicitlyReadonlyAtomic(NewProperty)))
+ return;
+
+ // Diagnose the conflict.
+ const IdentifierInfo *OldContextName;
+ auto *OldDC = OldProperty->getDeclContext();
+ if (auto Category = dyn_cast<ObjCCategoryDecl>(OldDC))
+ OldContextName = Category->getClassInterface()->getIdentifier();
+ else
+ OldContextName = cast<ObjCContainerDecl>(OldDC)->getIdentifier();
+
+ S.Diag(NewProperty->getLocation(), diag::warn_property_attribute)
+ << NewProperty->getDeclName() << "atomic"
+ << OldContextName;
+ S.Diag(OldProperty->getLocation(), diag::note_property_declare);
}
ObjCPropertyDecl *
@@ -308,11 +412,9 @@ Sema::HandlePropertyInClassExtension(Scope *S,
SourceLocation LParenLoc,
FieldDeclarator &FD,
Selector GetterSel, Selector SetterSel,
- const bool isAssign,
const bool isReadWrite,
- const unsigned Attributes,
+ unsigned &Attributes,
const unsigned AttributesAsWritten,
- bool *isOverridingProperty,
QualType T,
TypeSourceInfo *TSI,
tok::ObjCKeywordKind MethodImplKind) {
@@ -322,80 +424,102 @@ Sema::HandlePropertyInClassExtension(Scope *S,
IdentifierInfo *PropertyId = FD.D.getIdentifier();
ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
- if (CCPrimary) {
- // Check for duplicate declaration of this property in current and
- // other class extensions.
- for (const auto *Ext : CCPrimary->known_extensions()) {
- if (ObjCPropertyDecl *prevDecl
- = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) {
- Diag(AtLoc, diag::err_duplicate_property);
- Diag(prevDecl->getLocation(), diag::note_property_declare);
- return nullptr;
- }
- }
- }
-
- // Create a new ObjCPropertyDecl with the DeclContext being
- // the class extension.
- // FIXME. We should really be using CreatePropertyDecl for this.
- ObjCPropertyDecl *PDecl =
- ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
- PropertyId, AtLoc, LParenLoc, T, TSI);
- PDecl->setPropertyAttributesAsWritten(
- makePropertyAttributesAsWritten(AttributesAsWritten));
- if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
- if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
- if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
- if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
- if (Attributes & ObjCDeclSpec::DQ_PR_nullability)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
- if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable);
-
- // Set setter/getter selector name. Needed later.
- PDecl->setGetterName(GetterSel);
- PDecl->setSetterName(SetterSel);
- ProcessDeclAttributes(S, PDecl, FD.D);
- DC->addDecl(PDecl);
-
// We need to look in the @interface to see if the @property was
// already declared.
if (!CCPrimary) {
Diag(CDecl->getLocation(), diag::err_continuation_class);
- *isOverridingProperty = true;
return nullptr;
}
- // Find the property in continuation class's primary class only.
+ // Find the property in the extended class's primary class or
+ // extensions.
ObjCPropertyDecl *PIDecl =
CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
+ // If we found a property in an extension, complain.
+ if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) {
+ Diag(AtLoc, diag::err_duplicate_property);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ return nullptr;
+ }
+
+ // Check for consistency with the previous declaration, if there is one.
+ if (PIDecl) {
+ // A readonly property declared in the primary class can be refined
+ // by adding a readwrite property within an extension.
+ // Anything else is an error.
+ if (!(PIDecl->isReadOnly() && isReadWrite)) {
+ // Tailor the diagnostics for the common case where a readwrite
+ // property is declared both in the @interface and the continuation.
+ // This is a common error where the user often intended the original
+ // declaration to be readonly.
+ unsigned diag =
+ (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
+ (PIDecl->getPropertyAttributesAsWritten() &
+ ObjCPropertyDecl::OBJC_PR_readwrite)
+ ? diag::err_use_continuation_class_redeclaration_readwrite
+ : diag::err_use_continuation_class;
+ Diag(AtLoc, diag)
+ << CCPrimary->getDeclName();
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ return nullptr;
+ }
+
+ // Check for consistency of getters.
+ if (PIDecl->getGetterName() != GetterSel) {
+ // If the getter was written explicitly, complain.
+ if (AttributesAsWritten & ObjCDeclSpec::DQ_PR_getter) {
+ Diag(AtLoc, diag::warn_property_redecl_getter_mismatch)
+ << PIDecl->getGetterName() << GetterSel;
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+
+ // Always adopt the getter from the original declaration.
+ GetterSel = PIDecl->getGetterName();
+ Attributes |= ObjCDeclSpec::DQ_PR_getter;
+ }
+
+ // Check consistency of ownership.
+ unsigned ExistingOwnership
+ = getOwnershipRule(PIDecl->getPropertyAttributes());
+ unsigned NewOwnership = getOwnershipRule(Attributes);
+ if (ExistingOwnership && NewOwnership != ExistingOwnership) {
+ // If the ownership was written explicitly, complain.
+ if (getOwnershipRule(AttributesAsWritten)) {
+ Diag(AtLoc, diag::warn_property_attr_mismatch);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+
+ // Take the ownership from the original property.
+ Attributes = (Attributes & ~OwnershipMask) | ExistingOwnership;
+ }
+
+ // If the redeclaration is 'weak' but the original property is not,
+ if ((Attributes & ObjCPropertyDecl::OBJC_PR_weak) &&
+ !(PIDecl->getPropertyAttributesAsWritten()
+ & ObjCPropertyDecl::OBJC_PR_weak) &&
+ PIDecl->getType()->getAs<ObjCObjectPointerType>() &&
+ PIDecl->getType().getObjCLifetime() == Qualifiers::OCL_None) {
+ Diag(AtLoc, diag::warn_property_implicitly_mismatched);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+ }
+
+ // Create a new ObjCPropertyDecl with the DeclContext being
+ // the class extension.
+ ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc,
+ FD, GetterSel, SetterSel,
+ isReadWrite,
+ Attributes, AttributesAsWritten,
+ T, TSI, MethodImplKind, DC);
+
+ // If there was no declaration of a property with the same name in
+ // the primary class, we're done.
if (!PIDecl) {
- // No matching property found in the primary class. Just fall thru
- // and add property to continuation class's primary class.
- ObjCPropertyDecl *PrimaryPDecl =
- CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,
- FD, GetterSel, SetterSel, isAssign, isReadWrite,
- Attributes,AttributesAsWritten, T, TSI, MethodImplKind,
- DC);
-
- // A case of continuation class adding a new property in the class. This
- // is not what it was meant for. However, gcc supports it and so should we.
- // Make sure setter/getters are declared here.
- ProcessPropertyDecl(PrimaryPDecl, CCPrimary,
- /* redeclaredProperty = */ nullptr,
- /* lexicalDC = */ CDecl);
- PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());
- PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());
- if (ASTMutationListener *L = Context.getASTMutationListener())
- L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr,
- CDecl);
- return PrimaryPDecl;
+ ProcessPropertyDecl(PDecl);
+ return PDecl;
}
+
if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
bool IncompatibleObjC = false;
QualType ConvertedType;
@@ -418,103 +542,13 @@ Sema::HandlePropertyInClassExtension(Scope *S,
return nullptr;
}
}
-
- // The property 'PIDecl's readonly attribute will be over-ridden
- // with continuation class's readwrite property attribute!
- unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
- if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
- PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;
- PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;
- PIkind |= deduceWeakPropertyFromType(PIDecl->getType());
- unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
- unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
- if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&
- (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {
- Diag(AtLoc, diag::warn_property_attr_mismatch);
- Diag(PIDecl->getLocation(), diag::note_property_declare);
- }
- else if (getLangOpts().ObjCAutoRefCount) {
- QualType PrimaryPropertyQT =
- Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType();
- if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) {
- bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0);
- Qualifiers::ObjCLifetime PrimaryPropertyLifeTime =
- PrimaryPropertyQT.getObjCLifetime();
- if (PrimaryPropertyLifeTime == Qualifiers::OCL_None &&
- (Attributes & ObjCDeclSpec::DQ_PR_weak) &&
- !PropertyIsWeak) {
- Diag(AtLoc, diag::warn_property_implicitly_mismatched);
- Diag(PIDecl->getLocation(), diag::note_property_declare);
- }
- }
- }
-
- DeclContext *DC = cast<DeclContext>(CCPrimary);
- if (!ObjCPropertyDecl::findPropertyDecl(DC,
- PIDecl->getDeclName().getAsIdentifierInfo())) {
- // In mrr mode, 'readwrite' property must have an explicit
- // memory attribute. If none specified, select the default (assign).
- if (!getLangOpts().ObjCAutoRefCount) {
- if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign |
- ObjCDeclSpec::DQ_PR_retain |
- ObjCDeclSpec::DQ_PR_strong |
- ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_weak)))
- PIkind |= ObjCPropertyDecl::OBJC_PR_assign;
- }
-
- // Protocol is not in the primary class. Must build one for it.
- ObjCDeclSpec ProtocolPropertyODS;
- // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
- // and ObjCPropertyDecl::PropertyAttributeKind have identical
- // values. Should consolidate both into one enum type.
- ProtocolPropertyODS.
- setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
- PIkind);
- // Must re-establish the context from class extension to primary
- // class context.
- ContextRAII SavedContext(*this, CCPrimary);
-
- Decl *ProtocolPtrTy =
- ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS,
- PIDecl->getGetterName(),
- PIDecl->getSetterName(),
- isOverridingProperty,
- MethodImplKind,
- /* lexicalDC = */ CDecl);
- PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
- }
- PIDecl->makeitReadWriteAttribute();
- if (Attributes & ObjCDeclSpec::DQ_PR_retain)
- PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
- if (Attributes & ObjCDeclSpec::DQ_PR_strong)
- PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
- if (Attributes & ObjCDeclSpec::DQ_PR_copy)
- PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
- PIDecl->setSetterName(SetterSel);
- } else {
- // Tailor the diagnostics for the common case where a readwrite
- // property is declared both in the @interface and the continuation.
- // This is a common error where the user often intended the original
- // declaration to be readonly.
- unsigned diag =
- (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
- (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite)
- ? diag::err_use_continuation_class_redeclaration_readwrite
- : diag::err_use_continuation_class;
- Diag(AtLoc, diag)
- << CCPrimary->getDeclName();
- Diag(PIDecl->getLocation(), diag::note_property_declare);
- return nullptr;
- }
- *isOverridingProperty = true;
- // Make sure setter decl is synthesized, and added to primary class's list.
- ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);
- PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl());
- PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl());
- if (ASTMutationListener *L = Context.getASTMutationListener())
- L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl);
+
+ // Check that atomicity of property in class extension matches the previous
+ // declaration.
+ checkAtomicPropertyMismatch(*this, PIDecl, PDecl, true);
+
+ // Make sure getter/setter are appropriately synthesized.
+ ProcessPropertyDecl(PDecl);
return PDecl;
}
@@ -525,7 +559,6 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
FieldDeclarator &FD,
Selector GetterSel,
Selector SetterSel,
- const bool isAssign,
const bool isReadWrite,
const unsigned Attributes,
const unsigned AttributesAsWritten,
@@ -535,10 +568,23 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
DeclContext *lexicalDC){
IdentifierInfo *PropertyId = FD.D.getIdentifier();
- // Issue a warning if property is 'assign' as default and its object, which is
- // gc'able conforms to NSCopying protocol
+ // Property defaults to 'assign' if it is readwrite, unless this is ARC
+ // and the type is retainable.
+ bool isAssign;
+ if (Attributes & (ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_unsafe_unretained)) {
+ isAssign = true;
+ } else if (getOwnershipRule(Attributes) || !isReadWrite) {
+ isAssign = false;
+ } else {
+ isAssign = (!getLangOpts().ObjCAutoRefCount ||
+ !T->isObjCRetainableType());
+ }
+
+ // Issue a warning if property is 'assign' as default and its
+ // object, which is gc'able conforms to NSCopying protocol
if (getLangOpts().getGC() != LangOptions::NonGC &&
- isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
+ isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) {
if (const ObjCObjectPointerType *ObjPtrTy =
T->getAs<ObjCObjectPointerType>()) {
ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
@@ -548,6 +594,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
if (IDecl->ClassImplementsProtocol(PNSCopying, true))
Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
}
+ }
if (T->isObjCObjectType()) {
SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd();
@@ -663,8 +710,10 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
// We're fine if they match.
if (propertyLifetime == ivarLifetime) return;
- // These aren't valid lifetimes for object ivars; don't diagnose twice.
- if (ivarLifetime == Qualifiers::OCL_None ||
+ // None isn't a valid lifetime for an object ivar in ARC, and
+ // __autoreleasing is never valid; don't diagnose twice.
+ if ((ivarLifetime == Qualifiers::OCL_None &&
+ S.getLangOpts().ObjCAutoRefCount) ||
ivarLifetime == Qualifiers::OCL_Autoreleasing)
return;
@@ -797,6 +846,38 @@ DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc,
S.Diag(AtLoc, diag::note_property_synthesize);
}
+/// Determine whether any storage attributes were written on the property.
+static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop) {
+ if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true;
+
+ // If this is a readwrite property in a class extension that refines
+ // a readonly property in the original class definition, check it as
+ // well.
+
+ // If it's a readonly property, we're not interested.
+ if (Prop->isReadOnly()) return false;
+
+ // Is it declared in an extension?
+ auto Category = dyn_cast<ObjCCategoryDecl>(Prop->getDeclContext());
+ if (!Category || !Category->IsClassExtension()) return false;
+
+ // Find the corresponding property in the primary class definition.
+ auto OrigClass = Category->getClassInterface();
+ for (auto Found : OrigClass->lookup(Prop->getDeclName())) {
+ if (ObjCPropertyDecl *OrigProp = dyn_cast<ObjCPropertyDecl>(Found))
+ return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
+ }
+
+ // Look through all of the protocols.
+ for (const auto *Proto : OrigClass->all_referenced_protocols()) {
+ if (ObjCPropertyDecl *OrigProp =
+ Proto->FindPropertyDeclaration(Prop->getIdentifier()))
+ return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
+ }
+
+ return false;
+}
+
/// ActOnPropertyImplDecl - This routine performs semantic checks and
/// builds the AST node for a property implementation declaration; declared
/// as \@synthesize or \@dynamic.
@@ -953,18 +1034,49 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
ObjCPropertyDecl::PropertyAttributeKind kind
= property->getPropertyAttributes();
- // Add GC __weak to the ivar type if the property is weak.
- if ((kind & ObjCPropertyDecl::OBJC_PR_weak) &&
- getLangOpts().getGC() != LangOptions::NonGC) {
- assert(!getLangOpts().ObjCAutoRefCount);
- if (PropertyIvarType.isObjCGCStrong()) {
- Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
- Diag(property->getLocation(), diag::note_property_declare);
+ bool isARCWeak = false;
+ if (kind & ObjCPropertyDecl::OBJC_PR_weak) {
+ // Add GC __weak to the ivar type if the property is weak.
+ if (getLangOpts().getGC() != LangOptions::NonGC) {
+ assert(!getLangOpts().ObjCAutoRefCount);
+ if (PropertyIvarType.isObjCGCStrong()) {
+ Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
+ Diag(property->getLocation(), diag::note_property_declare);
+ } else {
+ PropertyIvarType =
+ Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
+ }
+
+ // Otherwise, check whether ARC __weak is enabled and works with
+ // the property type.
} else {
- PropertyIvarType =
- Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
+ if (!getLangOpts().ObjCWeak) {
+ // Only complain here when synthesizing an ivar.
+ if (!Ivar) {
+ Diag(PropertyDiagLoc,
+ getLangOpts().ObjCWeakRuntime
+ ? diag::err_synthesizing_arc_weak_property_disabled
+ : diag::err_synthesizing_arc_weak_property_no_runtime);
+ Diag(property->getLocation(), diag::note_property_declare);
+ }
+ CompleteTypeErr = true; // suppress later diagnostics about the ivar
+ } else {
+ isARCWeak = true;
+ if (const ObjCObjectPointerType *ObjT =
+ PropertyIvarType->getAs<ObjCObjectPointerType>()) {
+ const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
+ if (ObjI && ObjI->isArcWeakrefUnavailable()) {
+ Diag(property->getLocation(),
+ diag::err_arc_weak_unavailable_property)
+ << PropertyIvarType;
+ Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
+ << ClassImpDecl->getName();
+ }
+ }
+ }
}
}
+
if (AtLoc.isInvalid()) {
// Check when default synthesizing a property that there is
// an ivar matching property name and issue warning; since this
@@ -987,13 +1099,13 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (!Ivar) {
// In ARC, give the ivar a lifetime qualifier based on the
// property attributes.
- if (getLangOpts().ObjCAutoRefCount &&
+ if ((getLangOpts().ObjCAutoRefCount || isARCWeak) &&
!PropertyIvarType.getObjCLifetime() &&
PropertyIvarType->isObjCRetainableType()) {
// It's an error if we have to do this and the user didn't
// explicitly write an ownership attribute on the property.
- if (!property->hasWrittenStorageAttribute() &&
+ if (!hasWrittenStorageAttribute(property) &&
!(kind & ObjCPropertyDecl::OBJC_PR_strong)) {
Diag(PropertyDiagLoc,
diag::err_arc_objc_property_default_assign_on_object);
@@ -1002,24 +1114,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Qualifiers::ObjCLifetime lifetime =
getImpliedARCOwnership(kind, PropertyIvarType);
assert(lifetime && "no lifetime for property?");
- if (lifetime == Qualifiers::OCL_Weak) {
- bool err = false;
- if (const ObjCObjectPointerType *ObjT =
- PropertyIvarType->getAs<ObjCObjectPointerType>()) {
- const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
- if (ObjI && ObjI->isArcWeakrefUnavailable()) {
- Diag(property->getLocation(),
- diag::err_arc_weak_unavailable_property) << PropertyIvarType;
- Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
- << ClassImpDecl->getName();
- err = true;
- }
- }
- if (!err && !getLangOpts().ObjCARCWeak) {
- Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
- Diag(property->getLocation(), diag::note_property_declare);
- }
- }
Qualifiers qs;
qs.addObjCLifetime(lifetime);
@@ -1027,13 +1121,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
}
}
- if (kind & ObjCPropertyDecl::OBJC_PR_weak &&
- !getLangOpts().ObjCAutoRefCount &&
- getLangOpts().getGC() == LangOptions::NonGC) {
- Diag(PropertyDiagLoc, diag::error_synthesize_weak_non_arc_or_gc);
- Diag(property->getLocation(), diag::note_property_declare);
- }
-
Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
PropertyIvarType, /*Dinfo=*/nullptr,
@@ -1121,7 +1208,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// Fall thru - see previous comment
}
}
- if (getLangOpts().ObjCAutoRefCount)
+ if (getLangOpts().ObjCAutoRefCount || isARCWeak ||
+ Ivar->getType().getObjCLifetime())
checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
} else if (PropertyIvar)
// @dynamic
@@ -1349,12 +1437,10 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
}
}
- if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
- != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
- Diag(Property->getLocation(), diag::warn_property_attribute)
- << Property->getDeclName() << "atomic" << inheritedName;
- Diag(SuperProperty->getLocation(), diag::note_property_declare);
- }
+ // Check for nonatomic; note that nonatomic is effectively
+ // meaningless for readonly properties, so don't diagnose if the
+ // atomic property is 'readonly'.
+ checkAtomicPropertyMismatch(*this, SuperProperty, Property, false);
if (Property->getSetterName() != SuperProperty->getSetterName()) {
Diag(Property->getLocation(), diag::warn_property_attribute)
<< Property->getDeclName() << "setter" << inheritedName;
@@ -1395,12 +1481,11 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
QualType PropertyIvarType = property->getType().getNonReferenceType();
bool compat = Context.hasSameType(PropertyIvarType, GetterType);
if (!compat) {
- if (isa<ObjCObjectPointerType>(PropertyIvarType) &&
- isa<ObjCObjectPointerType>(GetterType))
- compat =
- Context.canAssignObjCInterfaces(
- GetterType->getAs<ObjCObjectPointerType>(),
- PropertyIvarType->getAs<ObjCObjectPointerType>());
+ const ObjCObjectPointerType *propertyObjCPtr = nullptr;
+ const ObjCObjectPointerType *getterObjCPtr = nullptr;
+ if ((propertyObjCPtr = PropertyIvarType->getAs<ObjCObjectPointerType>()) &&
+ (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>()))
+ compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr);
else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType)
!= Compatible) {
Diag(Loc, diag::error_property_accessor_type)
@@ -1438,6 +1523,11 @@ static void CollectImmediateProperties(ObjCContainerDecl *CDecl,
if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
for (auto *Prop : IDecl->properties())
PropMap[Prop->getIdentifier()] = Prop;
+
+ // Collect the properties from visible extensions.
+ for (auto *Ext : IDecl->visible_extensions())
+ CollectImmediateProperties(Ext, PropMap, SuperPropMap, IncludeProtocols);
+
if (IncludeProtocols) {
// Scan through class's protocols.
for (auto *PI : IDecl->all_referenced_protocols())
@@ -1445,9 +1535,8 @@ static void CollectImmediateProperties(ObjCContainerDecl *CDecl,
}
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- if (!CATDecl->IsClassExtension())
- for (auto *Prop : CATDecl->properties())
- PropMap[Prop->getIdentifier()] = Prop;
+ for (auto *Prop : CATDecl->properties())
+ PropMap[Prop->getIdentifier()] = Prop;
if (IncludeProtocols) {
// Scan through class's protocols.
for (auto *PI : CATDecl->protocols())
@@ -1507,6 +1596,14 @@ Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
(Property->getPropertyIvarDecl() == IV))
return true;
}
+ // Also look up property declaration in class extension whose one of its
+ // accessors is implemented by this method.
+ for (const auto *Ext : IFace->known_extensions())
+ for (const auto *Property : Ext->properties())
+ if ((Property->getGetterName() == IMD->getSelector() ||
+ Property->getSetterName() == IMD->getSelector()) &&
+ (Property->getPropertyIvarDecl() == IV))
+ return true;
return false;
}
@@ -1563,7 +1660,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
<< Prop->getIdentifier();
- if (!PID->getLocation().isInvalid())
+ if (PID->getLocation().isValid())
Diag(PID->getLocation(), diag::note_property_synthesize);
continue;
}
@@ -1791,11 +1888,20 @@ void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl)
void
Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
- ObjCContainerDecl* IDecl) {
+ ObjCInterfaceDecl* IDecl) {
// Rules apply in non-GC mode only
if (getLangOpts().getGC() != LangOptions::NonGC)
return;
- for (const auto *Property : IDecl->properties()) {
+ ObjCContainerDecl::PropertyMap PM;
+ for (auto *Prop : IDecl->properties())
+ PM[Prop->getIdentifier()] = Prop;
+ for (const auto *Ext : IDecl->known_extensions())
+ for (auto *Prop : Ext->properties())
+ PM[Prop->getIdentifier()] = Prop;
+
+ for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end();
+ I != E; ++I) {
+ const ObjCPropertyDecl *Property = I->second;
ObjCMethodDecl *GetterMethod = nullptr;
ObjCMethodDecl *SetterMethod = nullptr;
bool LookedUpGetterSetter = false;
@@ -1842,30 +1948,23 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
<< Property->getIdentifier() << (GetterMethod != nullptr)
<< (SetterMethod != nullptr);
// fixit stuff.
- if (!AttributesAsWritten) {
- if (Property->getLParenLoc().isValid()) {
- // @property () ... case.
- SourceRange PropSourceRange(Property->getAtLoc(),
- Property->getLParenLoc());
- Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
- FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic");
- }
- else {
- //@property id etc.
- SourceLocation endLoc =
- Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
- endLoc = endLoc.getLocWithOffset(-1);
- SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
- Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
- FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) ");
- }
- }
- else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
+ if (Property->getLParenLoc().isValid() &&
+ !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
// @property () ... case.
- SourceLocation endLoc = Property->getLParenLoc();
- SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
- Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
- FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, ");
+ SourceLocation AfterLParen =
+ getLocForEndOfToken(Property->getLParenLoc());
+ StringRef NonatomicStr = AttributesAsWritten? "nonatomic, "
+ : "nonatomic";
+ Diag(Property->getLocation(),
+ diag::note_atomic_property_fixup_suggest)
+ << FixItHint::CreateInsertion(AfterLParen, NonatomicStr);
+ } else if (Property->getLParenLoc().isInvalid()) {
+ //@property id etc.
+ SourceLocation startLoc =
+ Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
+ Diag(Property->getLocation(),
+ diag::note_atomic_property_fixup_suggest)
+ << FixItHint::CreateInsertion(startLoc, "(nonatomic) ");
}
else
Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
@@ -1950,10 +2049,16 @@ void Sema::DiagnoseMissingDesignatedInitOverrides(
I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) {
const ObjCMethodDecl *MD = *I;
if (!InitSelSet.count(MD->getSelector())) {
- Diag(ImplD->getLocation(),
- diag::warn_objc_implementation_missing_designated_init_override)
- << MD->getSelector();
- Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
+ bool Ignore = false;
+ if (auto *IMD = IFD->getInstanceMethod(MD->getSelector())) {
+ Ignore = IMD->isUnavailable();
+ }
+ if (!Ignore) {
+ Diag(ImplD->getLocation(),
+ diag::warn_objc_implementation_missing_designated_init_override)
+ << MD->getSelector();
+ Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
+ }
}
}
}
@@ -1974,20 +2079,28 @@ static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
/// have the property type and issue diagnostics if they don't.
/// Also synthesize a getter/setter method if none exist (and update the
-/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
-/// methods is the "right" thing to do.
-void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
- ObjCContainerDecl *CD,
- ObjCPropertyDecl *redeclaredProperty,
- ObjCContainerDecl *lexicalDC) {
-
+/// appropriate lookup tables.
+void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
ObjCMethodDecl *GetterMethod, *SetterMethod;
-
+ ObjCContainerDecl *CD = cast<ObjCContainerDecl>(property->getDeclContext());
if (CD->isInvalidDecl())
return;
GetterMethod = CD->getInstanceMethod(property->getGetterName());
+ // if setter or getter is not found in class extension, it might be
+ // in the primary class.
+ if (!GetterMethod)
+ if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
+ if (CatDecl->IsClassExtension())
+ GetterMethod = CatDecl->getClassInterface()->
+ getInstanceMethod(property->getGetterName());
+
SetterMethod = CD->getInstanceMethod(property->getSetterName());
+ if (!SetterMethod)
+ if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
+ if (CatDecl->IsClassExtension())
+ SetterMethod = CatDecl->getClassInterface()->
+ getInstanceMethod(property->getSetterName());
DiagnosePropertyAccessorMismatch(property, GetterMethod,
property->getLocation());
@@ -2020,9 +2133,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// No instance method of same name as property getter name was found.
// Declare a getter method and add it to the list of methods
// for this class.
- SourceLocation Loc = redeclaredProperty ?
- redeclaredProperty->getLocation() :
- property->getLocation();
+ SourceLocation Loc = property->getLocation();
// If the property is null_resettable, the getter returns nonnull.
QualType resultTy = property->getType();
@@ -2050,10 +2161,6 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
AddPropertyAttrs(*this, GetterMethod, property);
- // FIXME: Eventually this shouldn't be needed, as the lexical context
- // and the real context should be the same.
- if (lexicalDC)
- GetterMethod->setLexicalDeclContext(lexicalDC);
if (property->hasAttr<NSReturnsNotRetainedAttr>())
GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
Loc));
@@ -2082,9 +2189,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// No instance method of same name as property setter name was found.
// Declare a setter method and add it to the list of methods
// for this class.
- SourceLocation Loc = redeclaredProperty ?
- redeclaredProperty->getLocation() :
- property->getLocation();
+ SourceLocation Loc = property->getLocation();
SetterMethod =
ObjCMethodDecl::Create(Context, Loc, Loc,
@@ -2126,10 +2231,6 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
AddPropertyAttrs(*this, SetterMethod, property);
CD->addDecl(SetterMethod);
- // FIXME: Eventually this shouldn't be needed, as the lexical context
- // and the real context should be the same.
- if (lexicalDC)
- SetterMethod->setLexicalDeclContext(lexicalDC);
if (const SectionAttr *SA = property->getAttr<SectionAttr>())
SetterMethod->addAttr(
SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
@@ -2189,15 +2290,6 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
QualType PropertyTy = PropertyDecl->getType();
- unsigned PropertyOwnership = getOwnershipRule(Attributes);
-
- // 'readonly' property with no obvious lifetime.
- // its life time will be determined by its backing ivar.
- if (getLangOpts().ObjCAutoRefCount &&
- Attributes & ObjCDeclSpec::DQ_PR_readonly &&
- PropertyTy->isObjCRetainableType() &&
- !PropertyOwnership)
- return;
// Check for copy or retain on non-object types.
if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
@@ -2295,13 +2387,6 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
if (*nullability == NullabilityKind::NonNull)
Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
<< "nonnull" << "weak";
- } else {
- PropertyTy =
- Context.getAttributedType(
- AttributedType::getNullabilityAttrKind(NullabilityKind::Nullable),
- PropertyTy, PropertyTy);
- TypeSourceInfo *TSInfo = PropertyDecl->getTypeSourceInfo();
- PropertyDecl->setType(PropertyTy, TSInfo);
}
}
@@ -2314,16 +2399,14 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
// Warn if user supplied no assignment attribute, property is
// readwrite, and this is an object type.
- if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong |
- ObjCDeclSpec::DQ_PR_weak)) &&
- PropertyTy->isObjCObjectPointerType()) {
- if (getLangOpts().ObjCAutoRefCount)
- // With arc, @property definitions should default to (strong) when
- // not specified; including when property is 'readonly'.
- PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
- else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) {
+ if (!getOwnershipRule(Attributes) && PropertyTy->isObjCRetainableType()) {
+ if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
+ // do nothing
+ } else if (getLangOpts().ObjCAutoRefCount) {
+ // With arc, @property definitions should default to strong when
+ // not specified.
+ PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+ } else if (PropertyTy->isObjCObjectPointerType()) {
bool isAnyClassTy =
(PropertyTy->isObjCClassType() ||
PropertyTy->isObjCQualifiedClassType());
@@ -2342,7 +2425,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
if (getLangOpts().getGC() == LangOptions::NonGC)
Diag(Loc, diag::warn_objc_property_default_assign_on_object);
}
- }
+ }
// FIXME: Implement warning dependent on NSCopying being
// implemented. See also:
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index ca67a1c0bf24..5dd835498a9a 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -77,6 +77,11 @@ public:
ImplicitDSALoc() {}
};
+public:
+ struct MapInfo {
+ Expr *RefExpr;
+ };
+
private:
struct DSAInfo {
OpenMPClauseKind Attributes;
@@ -84,33 +89,41 @@ private:
};
typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;
typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy;
- typedef llvm::DenseSet<VarDecl *> LoopControlVariablesSetTy;
+ typedef llvm::DenseMap<VarDecl *, unsigned> LoopControlVariablesMapTy;
+ typedef llvm::SmallDenseMap<VarDecl *, MapInfo, 64> MappedDeclsTy;
+ typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
+ CriticalsWithHintsTy;
struct SharingMapTy {
DeclSAMapTy SharingMap;
AlignedMapTy AlignedMap;
- LoopControlVariablesSetTy LCVSet;
+ MappedDeclsTy MappedDecls;
+ LoopControlVariablesMapTy LCVMap;
DefaultDataSharingAttributes DefaultAttr;
SourceLocation DefaultAttrLoc;
OpenMPDirectiveKind Directive;
DeclarationNameInfo DirectiveName;
Scope *CurScope;
SourceLocation ConstructLoc;
- bool OrderedRegion;
+ /// \brief first argument (Expr *) contains optional argument of the
+ /// 'ordered' clause, the second one is true if the regions has 'ordered'
+ /// clause, false otherwise.
+ llvm::PointerIntPair<Expr *, 1, bool> OrderedRegion;
bool NowaitRegion;
- unsigned CollapseNumber;
+ bool CancelRegion;
+ unsigned AssociatedLoops;
SourceLocation InnerTeamsRegionLoc;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
- : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
+ : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified),
Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
- ConstructLoc(Loc), OrderedRegion(false), NowaitRegion(false),
- CollapseNumber(1), InnerTeamsRegionLoc() {}
+ ConstructLoc(Loc), OrderedRegion(), NowaitRegion(false),
+ CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {}
SharingMapTy()
- : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
+ : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified),
Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
- ConstructLoc(), OrderedRegion(false), NowaitRegion(false),
- CollapseNumber(1), InnerTeamsRegionLoc() {}
+ ConstructLoc(), OrderedRegion(), NowaitRegion(false),
+ CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {}
};
typedef SmallVector<SharingMapTy, 64> StackTy;
@@ -122,6 +135,7 @@ private:
OpenMPClauseKind ClauseKindMode;
Sema &SemaRef;
bool ForceCapturing;
+ CriticalsWithHintsTy Criticals;
typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
@@ -152,6 +166,16 @@ public:
Stack.pop_back();
}
+ void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) {
+ Criticals[D->getDirectiveName().getAsString()] = std::make_pair(D, Hint);
+ }
+ const std::pair<OMPCriticalDirective *, llvm::APSInt>
+ getCriticalWithHint(const DeclarationNameInfo &Name) const {
+ auto I = Criticals.find(Name.getAsString());
+ if (I != Criticals.end())
+ return I->second;
+ return std::make_pair(nullptr, llvm::APSInt());
+ }
/// \brief If 'aligned' declaration for given variable \a D was not seen yet,
/// add it and return NULL; otherwise return previous occurrence's expression
/// for diagnostics.
@@ -161,7 +185,17 @@ public:
void addLoopControlVariable(VarDecl *D);
/// \brief Check if the specified variable is a loop control variable for
/// current region.
- bool isLoopControlVariable(VarDecl *D);
+ /// \return The index of the loop control variable in the list of associated
+ /// for-loops (from outer to inner).
+ unsigned isLoopControlVariable(VarDecl *D);
+ /// \brief Check if the specified variable is a loop control variable for
+ /// parent region.
+ /// \return The index of the loop control variable in the list of associated
+ /// for-loops (from outer to inner).
+ unsigned isParentLoopControlVariable(VarDecl *D);
+ /// \brief Get the loop control variable for the I-th loop (or nullptr) in
+ /// parent directive.
+ VarDecl *getParentLoopControlVariable(unsigned I);
/// \brief Adds explicit data sharing attribute to the specified declaration.
void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A);
@@ -190,6 +224,13 @@ public:
bool hasExplicitDSA(VarDecl *D,
const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
unsigned Level);
+
+ /// \brief Returns true if the directive at level \Level matches in the
+ /// specified \a DPred predicate.
+ bool hasExplicitDirective(
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
+ unsigned Level);
+
/// \brief Finds a directive which matches specified \a DPred predicate.
template <class NamedDirectivesPredicate>
bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent);
@@ -204,6 +245,8 @@ public:
return Stack[Stack.size() - 2].Directive;
return OMPD_unknown;
}
+ /// \brief Return the directive associated with the provided scope.
+ OpenMPDirectiveKind getDirectiveForScope(const Scope *S) const;
/// \brief Set default data sharing attribute to none.
void setDefaultDSANone(SourceLocation Loc) {
@@ -230,16 +273,23 @@ public:
}
/// \brief Marks current region as ordered (it has an 'ordered' clause).
- void setOrderedRegion(bool IsOrdered = true) {
- Stack.back().OrderedRegion = IsOrdered;
+ void setOrderedRegion(bool IsOrdered, Expr *Param) {
+ Stack.back().OrderedRegion.setInt(IsOrdered);
+ Stack.back().OrderedRegion.setPointer(Param);
}
/// \brief Returns true, if parent region is ordered (has associated
/// 'ordered' clause), false - otherwise.
bool isParentOrderedRegion() const {
if (Stack.size() > 2)
- return Stack[Stack.size() - 2].OrderedRegion;
+ return Stack[Stack.size() - 2].OrderedRegion.getInt();
return false;
}
+ /// \brief Returns optional parameter for the ordered region.
+ Expr *getParentOrderedRegionParam() const {
+ if (Stack.size() > 2)
+ return Stack[Stack.size() - 2].OrderedRegion.getPointer();
+ return nullptr;
+ }
/// \brief Marks current region as nowait (it has a 'nowait' clause).
void setNowaitRegion(bool IsNowait = true) {
Stack.back().NowaitRegion = IsNowait;
@@ -251,13 +301,21 @@ public:
return Stack[Stack.size() - 2].NowaitRegion;
return false;
}
+ /// \brief Marks parent region as cancel region.
+ void setParentCancelRegion(bool Cancel = true) {
+ if (Stack.size() > 2)
+ Stack[Stack.size() - 2].CancelRegion =
+ Stack[Stack.size() - 2].CancelRegion || Cancel;
+ }
+ /// \brief Return true if current region has inner cancel construct.
+ bool isCancelRegion() const {
+ return Stack.back().CancelRegion;
+ }
/// \brief Set collapse value for the region.
- void setCollapseNumber(unsigned Val) { Stack.back().CollapseNumber = Val; }
+ void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops = Val; }
/// \brief Return collapse value for region.
- unsigned getCollapseNumber() const {
- return Stack.back().CollapseNumber;
- }
+ unsigned getAssociatedLoops() const { return Stack.back().AssociatedLoops; }
/// \brief Marks current target region as one with closely nested teams
/// region.
@@ -279,10 +337,37 @@ public:
Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
+
+ MapInfo getMapInfoForVar(VarDecl *VD) {
+ MapInfo VarMI = {0};
+ for (auto Cnt = Stack.size() - 1; Cnt > 0; --Cnt) {
+ if (Stack[Cnt].MappedDecls.count(VD)) {
+ VarMI = Stack[Cnt].MappedDecls[VD];
+ break;
+ }
+ }
+ return VarMI;
+ }
+
+ void addMapInfoForVar(VarDecl *VD, MapInfo MI) {
+ if (Stack.size() > 1) {
+ Stack.back().MappedDecls[VD] = MI;
+ }
+ }
+
+ MapInfo IsMappedInCurrentRegion(VarDecl *VD) {
+ assert(Stack.size() > 1 && "Target level is 0");
+ MapInfo VarMI = {0};
+ if (Stack.size() > 1 && Stack.back().MappedDecls.count(VD)) {
+ VarMI = Stack.back().MappedDecls[VD];
+ }
+ return VarMI;
+ }
};
bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
return isOpenMPParallelDirective(DKind) || DKind == OMPD_task ||
- isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown;
+ isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown ||
+ isOpenMPTaskLoopDirective(DKind);
}
} // namespace
@@ -409,13 +494,32 @@ DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {
void DSAStackTy::addLoopControlVariable(VarDecl *D) {
assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
D = D->getCanonicalDecl();
- Stack.back().LCVSet.insert(D);
+ Stack.back().LCVMap.insert(std::make_pair(D, Stack.back().LCVMap.size() + 1));
}
-bool DSAStackTy::isLoopControlVariable(VarDecl *D) {
+unsigned DSAStackTy::isLoopControlVariable(VarDecl *D) {
assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
D = D->getCanonicalDecl();
- return Stack.back().LCVSet.count(D) > 0;
+ return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] : 0;
+}
+
+unsigned DSAStackTy::isParentLoopControlVariable(VarDecl *D) {
+ assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
+ D = D->getCanonicalDecl();
+ return Stack[Stack.size() - 2].LCVMap.count(D) > 0
+ ? Stack[Stack.size() - 2].LCVMap[D]
+ : 0;
+}
+
+VarDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
+ assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
+ if (Stack[Stack.size() - 2].LCVMap.size() < I)
+ return nullptr;
+ for (auto &Pair : Stack[Stack.size() - 2].LCVMap) {
+ if (Pair.second == I)
+ return Pair.first;
+ }
+ return nullptr;
}
void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
@@ -452,12 +556,17 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
/// \brief Build a variable declaration for OpenMP loop iteration variable.
static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
- StringRef Name) {
+ StringRef Name, const AttrVec *Attrs = nullptr) {
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
VarDecl *Decl =
VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
+ if (Attrs) {
+ for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
+ I != E; ++I)
+ Decl->addAttr(*I);
+ }
Decl->setImplicit();
return Decl;
}
@@ -496,41 +605,20 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
}
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.1]
- // Variables with automatic storage duration that are declared in a scope
- // inside the construct are private.
- OpenMPDirectiveKind Kind =
- FromParent ? getParentDirective() : getCurrentDirective();
- auto StartI = std::next(Stack.rbegin());
- auto EndI = std::prev(Stack.rend());
- if (FromParent && StartI != EndI) {
- StartI = std::next(StartI);
- }
- if (!isParallelOrTaskRegion(Kind)) {
- if (isOpenMPLocal(D, StartI) &&
- ((D->isLocalVarDecl() && (D->getStorageClass() == SC_Auto ||
- D->getStorageClass() == SC_None)) ||
- isa<ParmVarDecl>(D))) {
- DVar.CKind = OMPC_private;
+ // in a Construct, C/C++, predetermined, p.4]
+ // Static data members are shared.
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.7]
+ // Variables with static storage duration that are declared in a scope
+ // inside the construct are shared.
+ if (D->isStaticDataMember()) {
+ DSAVarData DVarTemp =
+ hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent);
+ if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
return DVar;
- }
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.4]
- // Static data members are shared.
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.7]
- // Variables with static storage duration that are declared in a scope
- // inside the construct are shared.
- if (D->isStaticDataMember() || D->isStaticLocal()) {
- DSAVarData DVarTemp =
- hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent);
- if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
- return DVar;
-
- DVar.CKind = OMPC_shared;
- return DVar;
- }
+ DVar.CKind = OMPC_shared;
+ return DVar;
}
QualType Type = D->getType().getNonReferenceType().getCanonicalType();
@@ -542,6 +630,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
// shared.
CXXRecordDecl *RD =
SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
+ if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
+ if (auto *CTD = CTSD->getSpecializedTemplate())
+ RD = CTD->getTemplatedDecl();
if (IsConstant &&
!(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
// Variables with const-qualified type having no mutable member may be
@@ -557,6 +648,11 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
// Explicitly specified attributes and local variables with predetermined
// attributes.
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
auto I = std::prev(StartI);
if (I->SharingMap.count(D)) {
DVar.RefExpr = I->SharingMap[D].RefExpr;
@@ -635,6 +731,19 @@ bool DSAStackTy::hasExplicitDSA(
CPred(StartI->SharingMap[D].Attributes);
}
+bool DSAStackTy::hasExplicitDirective(
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
+ unsigned Level) {
+ if (isClauseParsingMode())
+ ++Level;
+ auto StartI = Stack.rbegin();
+ auto EndI = std::prev(Stack.rend());
+ if (std::distance(StartI, EndI) <= (int)Level)
+ return false;
+ std::advance(StartI, Level);
+ return DPred(StartI->Directive);
+}
+
template <class NamedDirectivesPredicate>
bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {
auto StartI = std::next(Stack.rbegin());
@@ -649,15 +758,134 @@ bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {
return false;
}
+OpenMPDirectiveKind DSAStackTy::getDirectiveForScope(const Scope *S) const {
+ for (auto I = Stack.rbegin(), EE = Stack.rend(); I != EE; ++I)
+ if (I->CurScope == S)
+ return I->Directive;
+ return OMPD_unknown;
+}
+
void Sema::InitDataSharingAttributesStack() {
VarDataSharingAttributesStack = new DSAStackTy(*this);
}
#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
+bool Sema::IsOpenMPCapturedByRef(VarDecl *VD,
+ const CapturedRegionScopeInfo *RSI) {
+ assert(LangOpts.OpenMP && "OpenMP is not allowed");
+
+ auto &Ctx = getASTContext();
+ bool IsByRef = true;
+
+ // Find the directive that is associated with the provided scope.
+ auto DKind = DSAStack->getDirectiveForScope(RSI->TheScope);
+ auto Ty = VD->getType();
+
+ if (isOpenMPTargetDirective(DKind)) {
+ // This table summarizes how a given variable should be passed to the device
+ // given its type and the clauses where it appears. This table is based on
+ // the description in OpenMP 4.5 [2.10.4, target Construct] and
+ // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
+ //
+ // =========================================================================
+ // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
+ // | |(tofrom:scalar)| | pvt | | | |
+ // =========================================================================
+ // | scl | | | | - | | bycopy|
+ // | scl | | - | x | - | - | bycopy|
+ // | scl | | x | - | - | - | null |
+ // | scl | x | | | - | | byref |
+ // | scl | x | - | x | - | - | bycopy|
+ // | scl | x | x | - | - | - | null |
+ // | scl | | - | - | - | x | byref |
+ // | scl | x | - | - | - | x | byref |
+ //
+ // | agg | n.a. | | | - | | byref |
+ // | agg | n.a. | - | x | - | - | byref |
+ // | agg | n.a. | x | - | - | - | null |
+ // | agg | n.a. | - | - | - | x | byref |
+ // | agg | n.a. | - | - | - | x[] | byref |
+ //
+ // | ptr | n.a. | | | - | | bycopy|
+ // | ptr | n.a. | - | x | - | - | bycopy|
+ // | ptr | n.a. | x | - | - | - | null |
+ // | ptr | n.a. | - | - | - | x | byref |
+ // | ptr | n.a. | - | - | - | x[] | bycopy|
+ // | ptr | n.a. | - | - | x | | bycopy|
+ // | ptr | n.a. | - | - | x | x | bycopy|
+ // | ptr | n.a. | - | - | x | x[] | bycopy|
+ // =========================================================================
+ // Legend:
+ // scl - scalar
+ // ptr - pointer
+ // agg - aggregate
+ // x - applies
+ // - - invalid in this combination
+ // [] - mapped with an array section
+ // byref - should be mapped by reference
+ // byval - should be mapped by value
+ // null - initialize a local variable to null on the device
+ //
+ // Observations:
+ // - All scalar declarations that show up in a map clause have to be passed
+ // by reference, because they may have been mapped in the enclosing data
+ // environment.
+ // - If the scalar value does not fit the size of uintptr, it has to be
+ // passed by reference, regardless the result in the table above.
+ // - For pointers mapped by value that have either an implicit map or an
+ // array section, the runtime library may pass the NULL value to the
+ // device instead of the value passed to it by the compiler.
+
+ // FIXME: Right now, only implicit maps are implemented. Properly mapping
+ // values requires having the map, private, and firstprivate clauses SEMA
+ // and parsing in place, which we don't yet.
+
+ if (Ty->isReferenceType())
+ Ty = Ty->castAs<ReferenceType>()->getPointeeType();
+ IsByRef = !Ty->isScalarType();
+ }
+
+ // When passing data by value, we need to make sure it fits the uintptr size
+ // and alignment, because the runtime library only deals with uintptr types.
+ // If it does not fit the uintptr size, we need to pass the data by reference
+ // instead.
+ if (!IsByRef &&
+ (Ctx.getTypeSizeInChars(Ty) >
+ Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
+ Ctx.getDeclAlign(VD) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType())))
+ IsByRef = true;
+
+ return IsByRef;
+}
+
bool Sema::IsOpenMPCapturedVar(VarDecl *VD) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
VD = VD->getCanonicalDecl();
+
+ // If we are attempting to capture a global variable in a directive with
+ // 'target' we return true so that this global is also mapped to the device.
+ //
+ // FIXME: If the declaration is enclosed in a 'declare target' directive,
+ // then it should not be captured. Therefore, an extra check has to be
+ // inserted here once support for 'declare target' is added.
+ //
+ if (!VD->hasLocalStorage()) {
+ if (DSAStack->getCurrentDirective() == OMPD_target &&
+ !DSAStack->isClauseParsingMode()) {
+ return true;
+ }
+ if (DSAStack->getCurScope() &&
+ DSAStack->hasDirective(
+ [](OpenMPDirectiveKind K, const DeclarationNameInfo &DNI,
+ SourceLocation Loc) -> bool {
+ return isOpenMPTargetDirective(K);
+ },
+ false)) {
+ return true;
+ }
+ }
+
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
(!DSAStack->isClauseParsingMode() ||
DSAStack->getParentDirective() != OMPD_unknown)) {
@@ -682,6 +910,14 @@ bool Sema::isOpenMPPrivateVar(VarDecl *VD, unsigned Level) {
VD, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level);
}
+bool Sema::isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level) {
+ assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ // Return true if the current level is no longer enclosed in a target region.
+
+ return !VD->hasLocalStorage() &&
+ DSAStack->hasExplicitDirective(isOpenMPTargetDirective, Level);
+}
+
void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
@@ -715,7 +951,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
continue;
}
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl());
- QualType Type = VD->getType();
+ QualType Type = VD->getType().getNonReferenceType();
auto DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_lastprivate) {
// Generate helper private variable and initialize it with the
@@ -723,9 +959,9 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
// by the address of the new private variable in CodeGen. This new
// variable is not added to IdResolver, so the code in the OpenMP
// region uses original variable for proper diagnostics.
- auto *VDPrivate =
- buildVarDecl(*this, DE->getExprLoc(), Type.getUnqualifiedType(),
- VD->getName());
+ auto *VDPrivate = buildVarDecl(
+ *this, DE->getExprLoc(), Type.getUnqualifiedType(),
+ VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr);
ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
if (VDPrivate->isInvalidDecl())
continue;
@@ -1158,7 +1394,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
switch (DKind) {
case OMPD_parallel: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1234,7 +1471,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_parallel_for: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1246,7 +1484,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_parallel_for_simd: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1258,7 +1497,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_parallel_sections: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1309,6 +1549,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_target_data:
case OMPD_target: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
@@ -1319,7 +1560,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_teams: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1337,6 +1579,30 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_taskloop: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_taskloop_simd: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_distribute: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_threadprivate:
case OMPD_taskyield:
case OMPD_barrier:
@@ -1356,6 +1622,10 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
ActOnCapturedRegionError();
return StmtError();
}
+
+ OMPOrderedClause *OC = nullptr;
+ OMPScheduleClause *SC = nullptr;
+ SmallVector<OMPLinearClause *, 4> LCs;
// This is required for proper codegen.
for (auto *Clause : Clauses) {
if (isOpenMPPrivate(Clause->getClauseKind()) ||
@@ -1377,10 +1647,42 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
// Required for proper codegen of combined directives.
// TODO: add processing for other clauses.
if (auto *E = cast_or_null<Expr>(
- cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) {
- MarkDeclarationsReferencedInExpr(E);
- }
+ cast<OMPScheduleClause>(Clause)->getHelperChunkSize()))
+ MarkDeclarationsReferencedInExpr(E);
}
+ if (Clause->getClauseKind() == OMPC_schedule)
+ SC = cast<OMPScheduleClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_ordered)
+ OC = cast<OMPOrderedClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_linear)
+ LCs.push_back(cast<OMPLinearClause>(Clause));
+ }
+ bool ErrorFound = false;
+ // OpenMP, 2.7.1 Loop Construct, Restrictions
+ // The nonmonotonic modifier cannot be specified if an ordered clause is
+ // specified.
+ if (SC &&
+ (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
+ SC->getSecondScheduleModifier() ==
+ OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
+ OC) {
+ Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
+ ? SC->getFirstScheduleModifierLoc()
+ : SC->getSecondScheduleModifierLoc(),
+ diag::err_omp_schedule_nonmonotonic_ordered)
+ << SourceRange(OC->getLocStart(), OC->getLocEnd());
+ ErrorFound = true;
+ }
+ if (!LCs.empty() && OC && OC->getNumForLoops()) {
+ for (auto *C : LCs) {
+ Diag(C->getLocStart(), diag::err_omp_linear_ordered)
+ << SourceRange(OC->getLocStart(), OC->getLocEnd());
+ }
+ ErrorFound = true;
+ }
+ if (ErrorFound) {
+ ActOnCapturedRegionError();
+ return StmtError();
}
return ActOnCapturedRegionEnd(S.get());
}
@@ -1419,6 +1721,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel | cancellation | |
// | | point | ! |
// | parallel | cancel | ! |
+ // | parallel | taskloop | * |
+ // | parallel | taskloop simd | * |
+ // | parallel | distribute | |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
@@ -1445,6 +1750,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for | cancellation | |
// | | point | ! |
// | for | cancel | ! |
+ // | for | taskloop | * |
+ // | for | taskloop simd | * |
+ // | for | distribute | |
// +------------------+-----------------+------------------------------------+
// | master | parallel | * |
// | master | for | + |
@@ -1471,6 +1779,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | master | cancellation | |
// | | point | |
// | master | cancel | |
+ // | master | taskloop | * |
+ // | master | taskloop simd | * |
+ // | master | distribute | |
// +------------------+-----------------+------------------------------------+
// | critical | parallel | * |
// | critical | for | + |
@@ -1496,6 +1807,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | critical | cancellation | |
// | | point | |
// | critical | cancel | |
+ // | critical | taskloop | * |
+ // | critical | taskloop simd | * |
+ // | critical | distribute | |
// +------------------+-----------------+------------------------------------+
// | simd | parallel | |
// | simd | for | |
@@ -1515,13 +1829,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | simd | taskwait | |
// | simd | taskgroup | |
// | simd | flush | |
- // | simd | ordered | |
+ // | simd | ordered | + (with simd clause) |
// | simd | atomic | |
// | simd | target | |
// | simd | teams | |
// | simd | cancellation | |
// | | point | |
// | simd | cancel | |
+ // | simd | taskloop | |
+ // | simd | taskloop simd | |
+ // | simd | distribute | |
// +------------------+-----------------+------------------------------------+
// | for simd | parallel | |
// | for simd | for | |
@@ -1541,13 +1858,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for simd | taskwait | |
// | for simd | taskgroup | |
// | for simd | flush | |
- // | for simd | ordered | |
+ // | for simd | ordered | + (with simd clause) |
// | for simd | atomic | |
// | for simd | target | |
// | for simd | teams | |
// | for simd | cancellation | |
// | | point | |
// | for simd | cancel | |
+ // | for simd | taskloop | |
+ // | for simd | taskloop simd | |
+ // | for simd | distribute | |
// +------------------+-----------------+------------------------------------+
// | parallel for simd| parallel | |
// | parallel for simd| for | |
@@ -1567,13 +1887,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for simd| taskwait | |
// | parallel for simd| taskgroup | |
// | parallel for simd| flush | |
- // | parallel for simd| ordered | |
+ // | parallel for simd| ordered | + (with simd clause) |
// | parallel for simd| atomic | |
// | parallel for simd| target | |
// | parallel for simd| teams | |
// | parallel for simd| cancellation | |
// | | point | |
// | parallel for simd| cancel | |
+ // | parallel for simd| taskloop | |
+ // | parallel for simd| taskloop simd | |
+ // | parallel for simd| distribute | |
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
@@ -1600,6 +1923,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | sections | cancellation | |
// | | point | ! |
// | sections | cancel | ! |
+ // | sections | taskloop | * |
+ // | sections | taskloop simd | * |
+ // | sections | distribute | |
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
@@ -1626,6 +1952,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | section | cancellation | |
// | | point | ! |
// | section | cancel | ! |
+ // | section | taskloop | * |
+ // | section | taskloop simd | * |
+ // | section | distribute | |
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
@@ -1652,6 +1981,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | single | cancellation | |
// | | point | |
// | single | cancel | |
+ // | single | taskloop | * |
+ // | single | taskloop simd | * |
+ // | single | distribute | |
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
@@ -1678,6 +2010,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for | cancellation | |
// | | point | ! |
// | parallel for | cancel | ! |
+ // | parallel for | taskloop | * |
+ // | parallel for | taskloop simd | * |
+ // | parallel for | distribute | |
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
@@ -1704,6 +2039,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel sections| cancellation | |
// | | point | ! |
// | parallel sections| cancel | ! |
+ // | parallel sections| taskloop | * |
+ // | parallel sections| taskloop simd | * |
+ // | parallel sections| distribute | |
// +------------------+-----------------+------------------------------------+
// | task | parallel | * |
// | task | for | + |
@@ -1730,6 +2068,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | task | cancellation | |
// | | point | ! |
// | task | cancel | ! |
+ // | task | taskloop | * |
+ // | task | taskloop simd | * |
+ // | task | distribute | |
// +------------------+-----------------+------------------------------------+
// | ordered | parallel | * |
// | ordered | for | + |
@@ -1756,6 +2097,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | ordered | cancellation | |
// | | point | |
// | ordered | cancel | |
+ // | ordered | taskloop | * |
+ // | ordered | taskloop simd | * |
+ // | ordered | distribute | |
// +------------------+-----------------+------------------------------------+
// | atomic | parallel | |
// | atomic | for | |
@@ -1782,6 +2126,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | atomic | cancellation | |
// | | point | |
// | atomic | cancel | |
+ // | atomic | taskloop | |
+ // | atomic | taskloop simd | |
+ // | atomic | distribute | |
// +------------------+-----------------+------------------------------------+
// | target | parallel | * |
// | target | for | * |
@@ -1808,6 +2155,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | target | cancellation | |
// | | point | |
// | target | cancel | |
+ // | target | taskloop | * |
+ // | target | taskloop simd | * |
+ // | target | distribute | |
// +------------------+-----------------+------------------------------------+
// | teams | parallel | * |
// | teams | for | + |
@@ -1834,6 +2184,95 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | teams | cancellation | |
// | | point | |
// | teams | cancel | |
+ // | teams | taskloop | + |
+ // | teams | taskloop simd | + |
+ // | teams | distribute | ! |
+ // +------------------+-----------------+------------------------------------+
+ // | taskloop | parallel | * |
+ // | taskloop | for | + |
+ // | taskloop | for simd | + |
+ // | taskloop | master | + |
+ // | taskloop | critical | * |
+ // | taskloop | simd | * |
+ // | taskloop | sections | + |
+ // | taskloop | section | + |
+ // | taskloop | single | + |
+ // | taskloop | parallel for | * |
+ // | taskloop |parallel for simd| * |
+ // | taskloop |parallel sections| * |
+ // | taskloop | task | * |
+ // | taskloop | taskyield | * |
+ // | taskloop | barrier | + |
+ // | taskloop | taskwait | * |
+ // | taskloop | taskgroup | * |
+ // | taskloop | flush | * |
+ // | taskloop | ordered | + |
+ // | taskloop | atomic | * |
+ // | taskloop | target | * |
+ // | taskloop | teams | + |
+ // | taskloop | cancellation | |
+ // | | point | |
+ // | taskloop | cancel | |
+ // | taskloop | taskloop | * |
+ // | taskloop | distribute | |
+ // +------------------+-----------------+------------------------------------+
+ // | taskloop simd | parallel | |
+ // | taskloop simd | for | |
+ // | taskloop simd | for simd | |
+ // | taskloop simd | master | |
+ // | taskloop simd | critical | |
+ // | taskloop simd | simd | |
+ // | taskloop simd | sections | |
+ // | taskloop simd | section | |
+ // | taskloop simd | single | |
+ // | taskloop simd | parallel for | |
+ // | taskloop simd |parallel for simd| |
+ // | taskloop simd |parallel sections| |
+ // | taskloop simd | task | |
+ // | taskloop simd | taskyield | |
+ // | taskloop simd | barrier | |
+ // | taskloop simd | taskwait | |
+ // | taskloop simd | taskgroup | |
+ // | taskloop simd | flush | |
+ // | taskloop simd | ordered | + (with simd clause) |
+ // | taskloop simd | atomic | |
+ // | taskloop simd | target | |
+ // | taskloop simd | teams | |
+ // | taskloop simd | cancellation | |
+ // | | point | |
+ // | taskloop simd | cancel | |
+ // | taskloop simd | taskloop | |
+ // | taskloop simd | taskloop simd | |
+ // | taskloop simd | distribute | |
+ // +------------------+-----------------+------------------------------------+
+ // | distribute | parallel | * |
+ // | distribute | for | * |
+ // | distribute | for simd | * |
+ // | distribute | master | * |
+ // | distribute | critical | * |
+ // | distribute | simd | * |
+ // | distribute | sections | * |
+ // | distribute | section | * |
+ // | distribute | single | * |
+ // | distribute | parallel for | * |
+ // | distribute |parallel for simd| * |
+ // | distribute |parallel sections| * |
+ // | distribute | task | * |
+ // | distribute | taskyield | * |
+ // | distribute | barrier | * |
+ // | distribute | taskwait | * |
+ // | distribute | taskgroup | * |
+ // | distribute | flush | * |
+ // | distribute | ordered | + |
+ // | distribute | atomic | * |
+ // | distribute | target | |
+ // | distribute | teams | |
+ // | distribute | cancellation | + |
+ // | | point | |
+ // | distribute | cancel | + |
+ // | distribute | taskloop | * |
+ // | distribute | taskloop simd | * |
+ // | distribute | distribute | |
// +------------------+-----------------+------------------------------------+
if (Stack->getCurScope()) {
auto ParentRegion = Stack->getParentDirective();
@@ -1843,11 +2282,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
NoRecommend,
ShouldBeInParallelRegion,
ShouldBeInOrderedRegion,
- ShouldBeInTargetRegion
+ ShouldBeInTargetRegion,
+ ShouldBeInTeamsRegion
} Recommend = NoRecommend;
- if (isOpenMPSimdDirective(ParentRegion)) {
+ if (isOpenMPSimdDirective(ParentRegion) && CurrentRegion != OMPD_ordered) {
// OpenMP [2.16, Nesting of Regions]
// OpenMP constructs may not be nested inside a simd region.
+ // OpenMP [2.8.1,simd Construct, Restrictions]
+ // An ordered construct with the simd clause is the only OpenMP construct
+ // that can appear in the simd region.
SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd);
return true;
}
@@ -1890,16 +2333,19 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// construct-type-clause.
NestingProhibited =
!((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) ||
- (CancelRegion == OMPD_for && ParentRegion == OMPD_for) ||
+ (CancelRegion == OMPD_for &&
+ (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for)) ||
(CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) ||
(CancelRegion == OMPD_sections &&
- (ParentRegion == OMPD_section || ParentRegion == OMPD_sections)));
+ (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
+ ParentRegion == OMPD_parallel_sections)));
} else if (CurrentRegion == OMPD_master) {
// OpenMP [2.16, Nesting of Regions]
// A master region may not be closely nested inside a worksharing,
// atomic, or explicit task region.
NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- ParentRegion == OMPD_task;
+ ParentRegion == OMPD_task ||
+ isOpenMPTaskLoopDirective(ParentRegion);
} else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
// OpenMP [2.16, Nesting of Regions]
// A critical region may not be nested (closely or otherwise) inside a
@@ -1936,7 +2382,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
NestingProhibited =
isOpenMPWorksharingDirective(ParentRegion) ||
ParentRegion == OMPD_task || ParentRegion == OMPD_master ||
- ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered ||
+ isOpenMPTaskLoopDirective(ParentRegion);
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
!isOpenMPParallelDirective(CurrentRegion)) {
// OpenMP [2.16, Nesting of Regions]
@@ -1945,7 +2392,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
NestingProhibited =
isOpenMPWorksharingDirective(ParentRegion) ||
ParentRegion == OMPD_task || ParentRegion == OMPD_master ||
- ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered ||
+ isOpenMPTaskLoopDirective(ParentRegion);
Recommend = ShouldBeInParallelRegion;
} else if (CurrentRegion == OMPD_ordered) {
// OpenMP [2.16, Nesting of Regions]
@@ -1953,9 +2401,14 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// atomic, or explicit task region.
// An ordered region must be closely nested inside a loop region (or
// parallel loop region) with an ordered clause.
+ // OpenMP [2.8.1,simd Construct, Restrictions]
+ // An ordered construct with the simd clause is the only OpenMP construct
+ // that can appear in the simd region.
NestingProhibited = ParentRegion == OMPD_critical ||
ParentRegion == OMPD_task ||
- !Stack->isParentOrderedRegion();
+ isOpenMPTaskLoopDirective(ParentRegion) ||
+ !(isOpenMPSimdDirective(ParentRegion) ||
+ Stack->isParentOrderedRegion());
Recommend = ShouldBeInOrderedRegion;
} else if (isOpenMPTeamsDirective(CurrentRegion)) {
// OpenMP [2.16, Nesting of Regions]
@@ -1970,10 +2423,17 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// distribute, parallel, parallel sections, parallel workshare, and the
// parallel loop and parallel loop SIMD constructs are the only OpenMP
// constructs that can be closely nested in the teams region.
- // TODO: add distribute directive.
- NestingProhibited = !isOpenMPParallelDirective(CurrentRegion);
+ NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
+ !isOpenMPDistributeDirective(CurrentRegion);
Recommend = ShouldBeInParallelRegion;
}
+ if (!NestingProhibited && isOpenMPDistributeDirective(CurrentRegion)) {
+ // OpenMP 4.5 [2.17 Nesting of Regions]
+ // The region associated with the distribute construct must be strictly
+ // nested inside a teams region
+ NestingProhibited = !isOpenMPTeamsDirective(ParentRegion);
+ Recommend = ShouldBeInTeamsRegion;
+ }
if (NestingProhibited) {
SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
<< CloseNesting << getOpenMPDirectiveName(ParentRegion) << Recommend
@@ -1984,6 +2444,88 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
return false;
}
+static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
+ ArrayRef<OMPClause *> Clauses,
+ ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
+ bool ErrorFound = false;
+ unsigned NamedModifiersNumber = 0;
+ SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers(
+ OMPD_unknown + 1);
+ SmallVector<SourceLocation, 4> NameModifierLoc;
+ for (const auto *C : Clauses) {
+ if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
+ // At most one if clause without a directive-name-modifier can appear on
+ // the directive.
+ OpenMPDirectiveKind CurNM = IC->getNameModifier();
+ if (FoundNameModifiers[CurNM]) {
+ S.Diag(C->getLocStart(), diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
+ << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
+ ErrorFound = true;
+ } else if (CurNM != OMPD_unknown) {
+ NameModifierLoc.push_back(IC->getNameModifierLoc());
+ ++NamedModifiersNumber;
+ }
+ FoundNameModifiers[CurNM] = IC;
+ if (CurNM == OMPD_unknown)
+ continue;
+ // Check if the specified name modifier is allowed for the current
+ // directive.
+ // At most one if clause with the particular directive-name-modifier can
+ // appear on the directive.
+ bool MatchFound = false;
+ for (auto NM : AllowedNameModifiers) {
+ if (CurNM == NM) {
+ MatchFound = true;
+ break;
+ }
+ }
+ if (!MatchFound) {
+ S.Diag(IC->getNameModifierLoc(),
+ diag::err_omp_wrong_if_directive_name_modifier)
+ << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
+ ErrorFound = true;
+ }
+ }
+ }
+ // If any if clause on the directive includes a directive-name-modifier then
+ // all if clauses on the directive must include a directive-name-modifier.
+ if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
+ if (NamedModifiersNumber == AllowedNameModifiers.size()) {
+ S.Diag(FoundNameModifiers[OMPD_unknown]->getLocStart(),
+ diag::err_omp_no_more_if_clause);
+ } else {
+ std::string Values;
+ std::string Sep(", ");
+ unsigned AllowedCnt = 0;
+ unsigned TotalAllowedNum =
+ AllowedNameModifiers.size() - NamedModifiersNumber;
+ for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
+ ++Cnt) {
+ OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
+ if (!FoundNameModifiers[NM]) {
+ Values += "'";
+ Values += getOpenMPDirectiveName(NM);
+ Values += "'";
+ if (AllowedCnt + 2 == TotalAllowedNum)
+ Values += " or ";
+ else if (AllowedCnt + 1 != TotalAllowedNum)
+ Values += Sep;
+ ++AllowedCnt;
+ }
+ }
+ S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(),
+ diag::err_omp_unnamed_if_clause)
+ << (TotalAllowedNum > 1) << Values;
+ }
+ for (auto Loc : NameModifierLoc) {
+ S.Diag(Loc, diag::note_omp_previous_named_if_clause);
+ }
+ ErrorFound = true;
+ }
+ return ErrorFound;
+}
+
StmtResult Sema::ActOnOpenMPExecutableDirective(
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
@@ -2020,10 +2562,12 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
}
}
+ llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
switch (Kind) {
case OMPD_parallel:
Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
+ AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_simd:
Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
@@ -2056,25 +2600,28 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
break;
case OMPD_critical:
- assert(ClausesWithImplicit.empty() &&
- "No clauses are allowed for 'omp critical' directive");
- Res = ActOnOpenMPCriticalDirective(DirName, AStmt, StartLoc, EndLoc);
+ Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
+ StartLoc, EndLoc);
break;
case OMPD_parallel_for:
Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_parallel_for_simd:
Res = ActOnOpenMPParallelForSimdDirective(
ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_parallel_sections:
Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
+ AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_task:
Res =
ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+ AllowedNameModifiers.push_back(OMPD_task);
break;
case OMPD_taskyield:
assert(ClausesWithImplicit.empty() &&
@@ -2108,9 +2655,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
break;
case OMPD_ordered:
- assert(ClausesWithImplicit.empty() &&
- "No clauses are allowed for 'omp ordered' directive");
- Res = ActOnOpenMPOrderedDirective(AStmt, StartLoc, EndLoc);
+ Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
break;
case OMPD_atomic:
Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
@@ -2123,6 +2669,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPD_target:
Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
+ AllowedNameModifiers.push_back(OMPD_target);
break;
case OMPD_cancellation_point:
assert(ClausesWithImplicit.empty() &&
@@ -2132,11 +2679,30 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
break;
case OMPD_cancel:
- assert(ClausesWithImplicit.empty() &&
- "No clauses are allowed for 'omp cancel' directive");
assert(AStmt == nullptr &&
"No associated statement allowed for 'omp cancel' directive");
- Res = ActOnOpenMPCancelDirective(StartLoc, EndLoc, CancelRegion);
+ Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
+ CancelRegion);
+ AllowedNameModifiers.push_back(OMPD_cancel);
+ break;
+ case OMPD_target_data:
+ Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ AllowedNameModifiers.push_back(OMPD_target_data);
+ break;
+ case OMPD_taskloop:
+ Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_taskloop);
+ break;
+ case OMPD_taskloop_simd:
+ Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_taskloop);
+ break;
+ case OMPD_distribute:
+ Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
break;
case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
@@ -2148,8 +2714,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
<< P.first << P.second->getSourceRange();
}
- if (!VarsWithInheritedDSA.empty())
- return StmtError();
+ ErrorFound = !VarsWithInheritedDSA.empty() || ErrorFound;
+
+ if (!AllowedNameModifiers.empty())
+ ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
+ ErrorFound;
if (ErrorFound)
return StmtError();
@@ -2160,7 +2729,9 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -2171,8 +2742,8 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
- return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses,
- AStmt);
+ return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ DSAStack->isCancelRegion());
}
namespace {
@@ -2247,6 +2818,9 @@ public:
Expr *BuildPreCond(Scope *S, Expr *Cond) const;
/// \brief Build reference expression to the counter be used for codegen.
Expr *BuildCounterVar() const;
+ /// \brief Build reference expression to the private counter be used for
+ /// codegen.
+ Expr *BuildPrivateCounterVar() const;
/// \brief Build initization of the counter be used for codegen.
Expr *BuildCounterInit() const;
/// \brief Build step of the counter be used for codegen.
@@ -2261,8 +2835,8 @@ private:
/// \brief Helper to set loop counter variable and its initializer.
bool SetVarAndLB(VarDecl *NewVar, DeclRefExpr *NewVarRefExpr, Expr *NewLB);
/// \brief Helper to set upper bound.
- bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, const SourceRange &SR,
- const SourceLocation &SL);
+ bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR,
+ SourceLocation SL);
/// \brief Helper to set loop increment.
bool SetStep(Expr *NewStep, bool Subtract);
};
@@ -2313,8 +2887,7 @@ bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar,
}
bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp,
- const SourceRange &SR,
- const SourceLocation &SL) {
+ SourceRange SR, SourceLocation SL) {
// State consistency checking to ensure correct usage.
assert(Var != nullptr && LB != nullptr && UB == nullptr && Step == nullptr &&
!TestIsLessOp && !TestIsStrictOp);
@@ -2410,7 +2983,7 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
} else if (auto DS = dyn_cast<DeclStmt>(S)) {
if (DS->isSingleDecl()) {
if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
- if (Var->hasInit()) {
+ if (Var->hasInit() && !Var->getType()->isReferenceType()) {
// Accept non-canonical init form here but emit ext. warning.
if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
SemaRef.Diag(S->getLocStart(),
@@ -2630,6 +3203,8 @@ public:
NewVD->setPreviousDeclInSameBlockScope(
VD->isPreviousDeclInSameBlockScope());
VD->getDeclContext()->addHiddenDecl(NewVD);
+ if (VD->hasAttrs())
+ NewVD->setAttrs(VD->getAttrs());
transformedLocalDecl(VD, NewVD);
return NewVD;
}
@@ -2802,7 +3377,21 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const {
/// \brief Build reference expression to the counter be used for codegen.
Expr *OpenMPIterationSpaceChecker::BuildCounterVar() const {
- return buildDeclRefExpr(SemaRef, Var, Var->getType(), DefaultLoc);
+ return buildDeclRefExpr(SemaRef, Var, Var->getType().getNonReferenceType(),
+ DefaultLoc);
+}
+
+Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
+ if (Var && !Var->isInvalidDecl()) {
+ auto Type = Var->getType().getNonReferenceType();
+ auto *PrivateVar =
+ buildVarDecl(SemaRef, DefaultLoc, Type, Var->getName(),
+ Var->hasAttrs() ? &Var->getAttrs() : nullptr);
+ if (PrivateVar->isInvalidDecl())
+ return nullptr;
+ return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
+ }
+ return nullptr;
}
/// \brief Build initization of the counter be used for codegen.
@@ -2820,6 +3409,8 @@ struct LoopIterationSpace {
Expr *NumIterations;
/// \brief The loop counter variable.
Expr *CounterVar;
+ /// \brief Private loop counter variable.
+ Expr *PrivateCounterVar;
/// \brief This is initializer for the initial value of #CounterVar.
Expr *CounterInit;
/// \brief This is step for the #CounterVar used to generate its update:
@@ -2840,14 +3431,13 @@ struct LoopIterationSpace {
void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
assert(getLangOpts().OpenMP && "OpenMP is not active.");
assert(Init && "Expected loop in canonical form.");
- unsigned CollapseIteration = DSAStack->getCollapseNumber();
- if (CollapseIteration > 0 &&
+ unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
+ if (AssociatedLoops > 0 &&
isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
OpenMPIterationSpaceChecker ISC(*this, ForLoc);
- if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) {
+ if (!ISC.CheckInit(Init, /*EmitDiags=*/false))
DSAStack->addLoopControlVariable(ISC.GetLoopVar());
- }
- DSAStack->setCollapseNumber(CollapseIteration - 1);
+ DSAStack->setAssociatedLoops(AssociatedLoops - 1);
}
}
@@ -2856,7 +3446,7 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
static bool CheckOpenMPIterationSpace(
OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
- Expr *NestedLoopCountExpr,
+ Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,
LoopIterationSpace &ResultIterSpace) {
// OpenMP [2.6, Canonical Loop Form]
@@ -2864,13 +3454,24 @@ static bool CheckOpenMPIterationSpace(
auto For = dyn_cast_or_null<ForStmt>(S);
if (!For) {
SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for)
- << (NestedLoopCountExpr != nullptr) << getOpenMPDirectiveName(DKind)
- << NestedLoopCount << (CurrentNestedLoopCount > 0)
- << CurrentNestedLoopCount;
- if (NestedLoopCount > 1)
- SemaRef.Diag(NestedLoopCountExpr->getExprLoc(),
- diag::note_omp_collapse_expr)
- << NestedLoopCountExpr->getSourceRange();
+ << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
+ << getOpenMPDirectiveName(DKind) << NestedLoopCount
+ << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
+ if (NestedLoopCount > 1) {
+ if (CollapseLoopCountExpr && OrderedLoopCountExpr)
+ SemaRef.Diag(DSA.getConstructLoc(),
+ diag::note_omp_collapse_ordered_expr)
+ << 2 << CollapseLoopCountExpr->getSourceRange()
+ << OrderedLoopCountExpr->getSourceRange();
+ else if (CollapseLoopCountExpr)
+ SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
+ diag::note_omp_collapse_ordered_expr)
+ << 0 << CollapseLoopCountExpr->getSourceRange();
+ else
+ SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
+ diag::note_omp_collapse_ordered_expr)
+ << 1 << OrderedLoopCountExpr->getSourceRange();
+ }
return true;
}
assert(For->getBody());
@@ -2893,7 +3494,7 @@ static bool CheckOpenMPIterationSpace(
// A variable of signed or unsigned integer type.
// For C++, a variable of a random access iterator type.
// For C, a variable of a pointer type.
- auto VarType = Var->getType();
+ auto VarType = Var->getType().getNonReferenceType();
if (!VarType->isDependentType() && !VarType->isIntegerType() &&
!VarType->isPointerType() &&
!(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
@@ -2929,12 +3530,12 @@ static bool CheckOpenMPIterationSpace(
? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
: OMPC_private;
if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
- DVar.CKind != OMPC_threadprivate && DVar.CKind != PredeterminedCKind) ||
- (isOpenMPWorksharingDirective(DKind) && !isOpenMPSimdDirective(DKind) &&
- DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private &&
- DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_threadprivate)) &&
- ((DVar.CKind != OMPC_private && DVar.CKind != OMPC_threadprivate) ||
- DVar.RefExpr != nullptr)) {
+ DVar.CKind != PredeterminedCKind) ||
+ ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
+ isOpenMPDistributeDirective(DKind)) &&
+ !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
+ DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
+ (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa)
<< getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
<< getOpenMPClauseName(PredeterminedCKind);
@@ -2945,7 +3546,8 @@ static bool CheckOpenMPIterationSpace(
} else if (LoopVarRefExpr != nullptr) {
// Make the loop iteration variable private (for worksharing constructs),
// linear (for simd directives with the only one associated loop) or
- // lastprivate (for simd directives with several collapsed loops).
+ // lastprivate (for simd directives with several collapsed or ordered
+ // loops).
if (DVar.CKind == OMPC_unknown)
DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(),
/*FromParent=*/false);
@@ -2966,8 +3568,11 @@ static bool CheckOpenMPIterationSpace(
// Build the loop's iteration space representation.
ResultIterSpace.PreCond = ISC.BuildPreCond(DSA.getCurScope(), For->getCond());
ResultIterSpace.NumIterations = ISC.BuildNumIterations(
- DSA.getCurScope(), /* LimitedType */ isOpenMPWorksharingDirective(DKind));
+ DSA.getCurScope(), (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind)));
ResultIterSpace.CounterVar = ISC.BuildCounterVar();
+ ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar();
ResultIterSpace.CounterInit = ISC.BuildCounterInit();
ResultIterSpace.CounterStep = ISC.BuildCounterStep();
ResultIterSpace.InitSrcRange = ISC.GetInitSrcRange();
@@ -2978,6 +3583,7 @@ static bool CheckOpenMPIterationSpace(
HasErrors |= (ResultIterSpace.PreCond == nullptr ||
ResultIterSpace.NumIterations == nullptr ||
ResultIterSpace.CounterVar == nullptr ||
+ ResultIterSpace.PrivateCounterVar == nullptr ||
ResultIterSpace.CounterInit == nullptr ||
ResultIterSpace.CounterStep == nullptr);
@@ -3091,17 +3697,33 @@ static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) {
/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
/// number of collapsed loops otherwise.
static unsigned
-CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
- Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA,
+CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
+ Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
+ DSAStackTy &DSA,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,
OMPLoopDirective::HelperExprs &Built) {
unsigned NestedLoopCount = 1;
- if (NestedLoopCountExpr) {
+ if (CollapseLoopCountExpr) {
// Found 'collapse' clause - calculate collapse number.
llvm::APSInt Result;
- if (NestedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
+ if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
NestedLoopCount = Result.getLimitedValue();
}
+ if (OrderedLoopCountExpr) {
+ // Found 'ordered' clause - calculate collapse number.
+ llvm::APSInt Result;
+ if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
+ if (Result.getLimitedValue() < NestedLoopCount) {
+ SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
+ diag::err_omp_wrong_ordered_loop_count)
+ << OrderedLoopCountExpr->getSourceRange();
+ SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
+ diag::note_collapse_loop_count)
+ << CollapseLoopCountExpr->getSourceRange();
+ }
+ NestedLoopCount = Result.getLimitedValue();
+ }
+ }
// This is helper routine for loop directives (e.g., 'for', 'simd',
// 'for simd', etc.).
SmallVector<LoopIterationSpace, 4> IterSpaces;
@@ -3109,8 +3731,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
- NestedLoopCount, NestedLoopCountExpr,
- VarsWithImplicitDSA, IterSpaces[Cnt]))
+ NestedLoopCount, CollapseLoopCountExpr,
+ OrderedLoopCountExpr, VarsWithImplicitDSA,
+ IterSpaces[Cnt]))
return 0;
// Move on to the next nested for loop, or to the loop body.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -3127,11 +3750,12 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// An example of what is generated for the following code:
//
- // #pragma omp simd collapse(2)
+ // #pragma omp simd collapse(2) ordered(2)
// for (i = 0; i < NI; ++i)
- // for (j = J0; j < NJ; j+=2) {
- // <loop body>
- // }
+ // for (k = 0; k < NK; ++k)
+ // for (j = J0; j < NJ; j+=2) {
+ // <loop body>
+ // }
//
// We generate the code below.
// Note: the loop body may be outlined in CodeGen.
@@ -3254,7 +3878,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
QualType VType = LastIteration.get()->getType();
// Build variables passed into runtime, nesessary for worksharing directives.
ExprResult LB, UB, IL, ST, EUB;
- if (isOpenMPWorksharingDirective(DKind)) {
+ if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind)) {
// Lower bound variable, initialized with zero.
VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
@@ -3302,7 +3927,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
{
VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.iv");
IV = buildDeclRefExpr(SemaRef, IVDecl, VType, InitLoc);
- Expr *RHS = isOpenMPWorksharingDirective(DKind)
+ Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind))
? LB.get()
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
@@ -3312,7 +3939,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops.
SourceLocation CondLoc;
ExprResult Cond =
- isOpenMPWorksharingDirective(DKind)
+ (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind))
? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get())
: SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
NumIterations.get());
@@ -3332,7 +3960,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
// Used for directives with static scheduling.
ExprResult NextLB, NextUB;
- if (isOpenMPWorksharingDirective(DKind)) {
+ if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind)) {
// LB + ST
NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
if (!NextLB.isUsable())
@@ -3437,6 +4066,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
}
// Save results
Built.Counters[Cnt] = IS.CounterVar;
+ Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
Built.Inits[Cnt] = Init.get();
Built.Updates[Cnt] = Update.get();
Built.Finals[Cnt] = Final.get();
@@ -3467,26 +4097,60 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
return NestedLoopCount;
}
-static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
- auto &&CollapseFilter = [](const OMPClause *C) -> bool {
- return C->getClauseKind() == OMPC_collapse;
- };
- OMPExecutableDirective::filtered_clause_iterator<decltype(CollapseFilter)> I(
- Clauses, std::move(CollapseFilter));
- if (I)
- return cast<OMPCollapseClause>(*I)->getNumForLoops();
+static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
+ auto CollapseClauses =
+ OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
+ if (CollapseClauses.begin() != CollapseClauses.end())
+ return (*CollapseClauses.begin())->getNumForLoops();
+ return nullptr;
+}
+
+static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
+ auto OrderedClauses =
+ OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
+ if (OrderedClauses.begin() != OrderedClauses.end())
+ return (*OrderedClauses.begin())->getNumForLoops();
return nullptr;
}
+static bool checkSimdlenSafelenValues(Sema &S, const Expr *Simdlen,
+ const Expr *Safelen) {
+ llvm::APSInt SimdlenRes, SafelenRes;
+ if (Simdlen->isValueDependent() || Simdlen->isTypeDependent() ||
+ Simdlen->isInstantiationDependent() ||
+ Simdlen->containsUnexpandedParameterPack())
+ return false;
+ if (Safelen->isValueDependent() || Safelen->isTypeDependent() ||
+ Safelen->isInstantiationDependent() ||
+ Safelen->containsUnexpandedParameterPack())
+ return false;
+ Simdlen->EvaluateAsInt(SimdlenRes, S.Context);
+ Safelen->EvaluateAsInt(SafelenRes, S.Context);
+ // OpenMP 4.1 [2.8.1, simd Construct, Restrictions]
+ // If both simdlen and safelen clauses are specified, the value of the simdlen
+ // parameter must be less than or equal to the value of the safelen parameter.
+ if (SimdlenRes > SafelenRes) {
+ S.Diag(Simdlen->getExprLoc(), diag::err_omp_wrong_simdlen_safelen_values)
+ << Simdlen->getSourceRange() << Safelen->getSourceRange();
+ return true;
+ }
+ return false;
+}
+
StmtResult Sema::ActOnOpenMPSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
- unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this,
- *DSAStack, VarsWithImplicitDSA, B);
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount = CheckOpenMPLoop(
+ OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
+ AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -3503,6 +4167,24 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
}
}
+ // OpenMP 4.1 [2.8.1, simd Construct, Restrictions]
+ // If both simdlen and safelen clauses are specified, the value of the simdlen
+ // parameter must be less than or equal to the value of the safelen parameter.
+ OMPSafelenClause *Safelen = nullptr;
+ OMPSimdlenClause *Simdlen = nullptr;
+ for (auto *Clause : Clauses) {
+ if (Clause->getClauseKind() == OMPC_safelen)
+ Safelen = cast<OMPSafelenClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_simdlen)
+ Simdlen = cast<OMPSimdlenClause>(Clause);
+ if (Safelen && Simdlen)
+ break;
+ }
+ if (Simdlen && Safelen &&
+ checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(),
+ Safelen->getSafelen()))
+ return StmtError();
+
getCurFunction()->setHasBranchProtectedScope();
return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
@@ -3512,31 +4194,52 @@ StmtResult Sema::ActOnOpenMPForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
- unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this,
- *DSAStack, VarsWithImplicitDSA, B);
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount = CheckOpenMPLoop(
+ OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
+ AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope))
+ return StmtError();
+ }
+ }
+
getCurFunction()->setHasBranchProtectedScope();
return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
- Clauses, AStmt, B);
+ Clauses, AStmt, B, DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_for_simd, GetCollapseNumberExpr(Clauses), AStmt,
- *this, *DSAStack, VarsWithImplicitDSA, B);
+ CheckOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
+ getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -3553,6 +4256,24 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
}
}
+ // OpenMP 4.1 [2.8.1, simd Construct, Restrictions]
+ // If both simdlen and safelen clauses are specified, the value of the simdlen
+ // parameter must be less than or equal to the value of the safelen parameter.
+ OMPSafelenClause *Safelen = nullptr;
+ OMPSimdlenClause *Simdlen = nullptr;
+ for (auto *Clause : Clauses) {
+ if (Clause->getClauseKind() == OMPC_safelen)
+ Safelen = cast<OMPSafelenClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_simdlen)
+ Simdlen = cast<OMPSimdlenClause>(Clause);
+ if (Safelen && Simdlen)
+ break;
+ }
+ if (Simdlen && Safelen &&
+ checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(),
+ Safelen->getSafelen()))
+ return StmtError();
+
getCurFunction()->setHasBranchProtectedScope();
return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
@@ -3562,23 +4283,28 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
auto BaseStmt = AStmt;
while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
BaseStmt = CS->getCapturedStmt();
if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
auto S = C->children();
- if (!S)
+ if (S.begin() == S.end())
return StmtError();
// All associated statements must be '#pragma omp section' except for
// the first one.
- for (Stmt *SectionStmt : ++S) {
+ for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
Diag(SectionStmt->getLocStart(),
diag::err_omp_sections_substmt_not_section);
return StmtError();
}
+ cast<OMPSectionDirective>(SectionStmt)
+ ->setHasCancel(DSAStack->isCancelRegion());
}
} else {
Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt);
@@ -3587,25 +4313,33 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
- return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses,
- AStmt);
+ return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
+ DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
- return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt);
+ return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@@ -3632,30 +4366,81 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
-StmtResult
-Sema::ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+StmtResult Sema::ActOnOpenMPCriticalDirective(
+ const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ bool ErrorFound = false;
+ llvm::APSInt Hint;
+ SourceLocation HintLoc;
+ bool DependentHint = false;
+ for (auto *C : Clauses) {
+ if (C->getClauseKind() == OMPC_hint) {
+ if (!DirName.getName()) {
+ Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name);
+ ErrorFound = true;
+ }
+ Expr *E = cast<OMPHintClause>(C)->getHint();
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ E->isInstantiationDependent())
+ DependentHint = true;
+ else {
+ Hint = E->EvaluateKnownConstInt(Context);
+ HintLoc = C->getLocStart();
+ }
+ }
+ }
+ if (ErrorFound)
+ return StmtError();
+ auto Pair = DSAStack->getCriticalWithHint(DirName);
+ if (Pair.first && DirName.getName() && !DependentHint) {
+ if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
+ Diag(StartLoc, diag::err_omp_critical_with_hint);
+ if (HintLoc.isValid()) {
+ Diag(HintLoc, diag::note_omp_critical_hint_here)
+ << 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false);
+ } else
+ Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
+ if (auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
+ Diag(C->getLocStart(), diag::note_omp_critical_hint_here)
+ << 1
+ << C->getHint()->EvaluateKnownConstInt(Context).toString(
+ /*Radix=*/10, /*Signed=*/false);
+ } else
+ Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1;
+ }
+ }
getCurFunction()->setHasBranchProtectedScope();
- return OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
- AStmt);
+ auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
+ Clauses, AStmt);
+ if (!Pair.first && DirName.getName() && !DependentHint)
+ DSAStack->addCriticalWithHint(Dir, Hint);
+ return Dir;
}
StmtResult Sema::ActOnOpenMPParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -3665,26 +4450,41 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
CS->getCapturedDecl()->setNothrow();
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_parallel_for, GetCollapseNumberExpr(Clauses), AStmt,
- *this, *DSAStack, VarsWithImplicitDSA, B);
+ CheckOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
+ getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp parallel for loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope))
+ return StmtError();
+ }
+ }
+
getCurFunction()->setHasBranchProtectedScope();
return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
- NestedLoopCount, Clauses, AStmt, B);
+ NestedLoopCount, Clauses, AStmt, B,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -3694,10 +4494,12 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
CS->getCapturedDecl()->setNothrow();
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_parallel_for_simd, GetCollapseNumberExpr(Clauses),
- AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
+ CheckOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
+ getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -3711,6 +4513,24 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
}
}
+ // OpenMP 4.1 [2.8.1, simd Construct, Restrictions]
+ // If both simdlen and safelen clauses are specified, the value of the simdlen
+ // parameter must be less than or equal to the value of the safelen parameter.
+ OMPSafelenClause *Safelen = nullptr;
+ OMPSimdlenClause *Simdlen = nullptr;
+ for (auto *Clause : Clauses) {
+ if (Clause->getClauseKind() == OMPC_safelen)
+ Safelen = cast<OMPSafelenClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_simdlen)
+ Simdlen = cast<OMPSimdlenClause>(Clause);
+ if (Safelen && Simdlen)
+ break;
+ }
+ if (Simdlen && Safelen &&
+ checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(),
+ Safelen->getSafelen()))
+ return StmtError();
+
getCurFunction()->setHasBranchProtectedScope();
return OMPParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
@@ -3720,23 +4540,28 @@ StmtResult
Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
auto BaseStmt = AStmt;
while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
BaseStmt = CS->getCapturedStmt();
if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
auto S = C->children();
- if (!S)
+ if (S.begin() == S.end())
return StmtError();
// All associated statements must be '#pragma omp section' except for
// the first one.
- for (Stmt *SectionStmt : ++S) {
+ for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
Diag(SectionStmt->getLocStart(),
diag::err_omp_parallel_sections_substmt_not_section);
return StmtError();
}
+ cast<OMPSectionDirective>(SectionStmt)
+ ->setHasCancel(DSAStack->isCancelRegion());
}
} else {
Diag(AStmt->getLocStart(),
@@ -3746,14 +4571,16 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
- return OMPParallelSectionsDirective::Create(Context, StartLoc, EndLoc,
- Clauses, AStmt);
+ return OMPParallelSectionsDirective::Create(
+ Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -3764,7 +4591,8 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
- return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+ return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
@@ -3785,7 +4613,10 @@ StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
StmtResult Sema::ActOnOpenMPTaskgroupDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@@ -3799,14 +4630,79 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
}
-StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt,
+StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ OMPClause *DependFound = nullptr;
+ OMPClause *DependSourceClause = nullptr;
+ OMPClause *DependSinkClause = nullptr;
+ bool ErrorFound = false;
+ OMPThreadsClause *TC = nullptr;
+ OMPSIMDClause *SC = nullptr;
+ for (auto *C : Clauses) {
+ if (auto *DC = dyn_cast<OMPDependClause>(C)) {
+ DependFound = C;
+ if (DC->getDependencyKind() == OMPC_DEPEND_source) {
+ if (DependSourceClause) {
+ Diag(C->getLocStart(), diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(OMPD_ordered)
+ << getOpenMPClauseName(OMPC_depend) << 2;
+ ErrorFound = true;
+ } else
+ DependSourceClause = C;
+ if (DependSinkClause) {
+ Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
+ << 0;
+ ErrorFound = true;
+ }
+ } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
+ if (DependSourceClause) {
+ Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
+ << 1;
+ ErrorFound = true;
+ }
+ DependSinkClause = C;
+ }
+ } else if (C->getClauseKind() == OMPC_threads)
+ TC = cast<OMPThreadsClause>(C);
+ else if (C->getClauseKind() == OMPC_simd)
+ SC = cast<OMPSIMDClause>(C);
+ }
+ if (!ErrorFound && !SC &&
+ isOpenMPSimdDirective(DSAStack->getParentDirective())) {
+ // OpenMP [2.8.1,simd Construct, Restrictions]
+ // An ordered construct with the simd clause is the only OpenMP construct
+ // that can appear in the simd region.
+ Diag(StartLoc, diag::err_omp_prohibited_region_simd);
+ ErrorFound = true;
+ } else if (DependFound && (TC || SC)) {
+ Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd)
+ << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
+ ErrorFound = true;
+ } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) {
+ Diag(DependFound->getLocStart(),
+ diag::err_omp_ordered_directive_without_param);
+ ErrorFound = true;
+ } else if (TC || Clauses.empty()) {
+ if (auto *Param = DSAStack->getParentOrderedRegionParam()) {
+ SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc;
+ Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
+ << (TC != nullptr);
+ Diag(Param->getLocStart(), diag::note_omp_ordered_param);
+ ErrorFound = true;
+ }
+ }
+ if ((!AStmt && !DependFound) || ErrorFound)
+ return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ if (AStmt) {
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt);
+ getCurFunction()->setHasBranchProtectedScope();
+ }
+
+ return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
namespace {
@@ -4006,7 +4902,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
NoteLoc = AtomicUnaryOp->getOperatorLoc();
NoteRange = SourceRange(NoteLoc, NoteLoc);
}
- } else {
+ } else if (!AtomicBody->isInstantiationDependent()) {
ErrorFound = NotABinaryOrUnaryExpression;
NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
NoteRange = ErrorRange = AtomicBody->getSourceRange();
@@ -4053,7 +4949,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
auto CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -4150,7 +5048,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
NoteLoc = NotScalarExpr->getExprLoc();
NoteRange = NotScalarExpr->getSourceRange();
}
- } else {
+ } else if (!AtomicBody->isInstantiationDependent()) {
ErrorFound = NotAnAssignmentOp;
ErrorLoc = AtomicBody->getExprLoc();
ErrorRange = AtomicBody->getSourceRange();
@@ -4211,7 +5109,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
NoteLoc = NotScalarExpr->getExprLoc();
NoteRange = NotScalarExpr->getSourceRange();
}
- } else {
+ } else if (!AtomicBody->isInstantiationDependent()) {
ErrorFound = NotAnAssignmentOp;
ErrorLoc = AtomicBody->getExprLoc();
ErrorRange = AtomicBody->getSourceRange();
@@ -4289,7 +5187,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
UE = Checker.getUpdateExpr();
IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
IsPostfixUpdate = Checker.isPostfixUpdate();
- } else {
+ } else if (!AtomicBody->isInstantiationDependent()) {
ErrorLoc = AtomicBody->getExprLoc();
ErrorRange = AtomicBody->getSourceRange();
NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
@@ -4396,46 +5294,54 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
if (!IsUpdateExprFound) {
// { v = x; x = expr; }
- auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
- if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
- ErrorFound = NotAnAssignmentOp;
- NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
- : First->getLocStart();
- NoteRange = ErrorRange = FirstBinOp
- ? FirstBinOp->getSourceRange()
- : SourceRange(ErrorLoc, ErrorLoc);
- } else {
- auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
- if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
+ auto *FirstExpr = dyn_cast<Expr>(First);
+ auto *SecondExpr = dyn_cast<Expr>(Second);
+ if (!FirstExpr || !SecondExpr ||
+ !(FirstExpr->isInstantiationDependent() ||
+ SecondExpr->isInstantiationDependent())) {
+ auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
+ if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
ErrorFound = NotAnAssignmentOp;
- NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc()
- : Second->getLocStart();
- NoteRange = ErrorRange = SecondBinOp
- ? SecondBinOp->getSourceRange()
+ NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
+ : First->getLocStart();
+ NoteRange = ErrorRange = FirstBinOp
+ ? FirstBinOp->getSourceRange()
: SourceRange(ErrorLoc, ErrorLoc);
} else {
- auto *PossibleXRHSInFirst =
- FirstBinOp->getRHS()->IgnoreParenImpCasts();
- auto *PossibleXLHSInSecond =
- SecondBinOp->getLHS()->IgnoreParenImpCasts();
- llvm::FoldingSetNodeID X1Id, X2Id;
- PossibleXRHSInFirst->Profile(X1Id, Context, /*Canonical=*/true);
- PossibleXLHSInSecond->Profile(X2Id, Context,
- /*Canonical=*/true);
- IsUpdateExprFound = X1Id == X2Id;
- if (IsUpdateExprFound) {
- V = FirstBinOp->getLHS();
- X = SecondBinOp->getLHS();
- E = SecondBinOp->getRHS();
- UE = nullptr;
- IsXLHSInRHSPart = false;
- IsPostfixUpdate = true;
+ auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
+ if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
+ ErrorFound = NotAnAssignmentOp;
+ NoteLoc = ErrorLoc = SecondBinOp
+ ? SecondBinOp->getOperatorLoc()
+ : Second->getLocStart();
+ NoteRange = ErrorRange =
+ SecondBinOp ? SecondBinOp->getSourceRange()
+ : SourceRange(ErrorLoc, ErrorLoc);
} else {
- ErrorFound = NotASpecificExpression;
- ErrorLoc = FirstBinOp->getExprLoc();
- ErrorRange = FirstBinOp->getSourceRange();
- NoteLoc = SecondBinOp->getLHS()->getExprLoc();
- NoteRange = SecondBinOp->getRHS()->getSourceRange();
+ auto *PossibleXRHSInFirst =
+ FirstBinOp->getRHS()->IgnoreParenImpCasts();
+ auto *PossibleXLHSInSecond =
+ SecondBinOp->getLHS()->IgnoreParenImpCasts();
+ llvm::FoldingSetNodeID X1Id, X2Id;
+ PossibleXRHSInFirst->Profile(X1Id, Context,
+ /*Canonical=*/true);
+ PossibleXLHSInSecond->Profile(X2Id, Context,
+ /*Canonical=*/true);
+ IsUpdateExprFound = X1Id == X2Id;
+ if (IsUpdateExprFound) {
+ V = FirstBinOp->getLHS();
+ X = SecondBinOp->getLHS();
+ E = SecondBinOp->getRHS();
+ UE = nullptr;
+ IsXLHSInRHSPart = false;
+ IsPostfixUpdate = true;
+ } else {
+ ErrorFound = NotASpecificExpression;
+ ErrorLoc = FirstBinOp->getExprLoc();
+ ErrorRange = FirstBinOp->getSourceRange();
+ NoteLoc = SecondBinOp->getLHS()->getExprLoc();
+ NoteRange = SecondBinOp->getRHS()->getSourceRange();
+ }
}
}
}
@@ -4474,7 +5380,16 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
// OpenMP [2.16, Nesting of Regions]
// If specified, a teams construct must be contained within a target
@@ -4511,10 +5426,27 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
+StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ AStmt);
+}
+
StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -4550,7 +5482,8 @@ Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
CancelRegion);
}
-StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc,
+StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion) {
if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for &&
@@ -4567,7 +5500,123 @@ StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc,
Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
return StmtError();
}
- return OMPCancelDirective::Create(Context, StartLoc, EndLoc, CancelRegion);
+ DSAStack->setParentCancelRegion(/*Cancel=*/true);
+ return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ CancelRegion);
+}
+
+static bool checkGrainsizeNumTasksClauses(Sema &S,
+ ArrayRef<OMPClause *> Clauses) {
+ OMPClause *PrevClause = nullptr;
+ bool ErrorFound = false;
+ for (auto *C : Clauses) {
+ if (C->getClauseKind() == OMPC_grainsize ||
+ C->getClauseKind() == OMPC_num_tasks) {
+ if (!PrevClause)
+ PrevClause = C;
+ else if (PrevClause->getClauseKind() != C->getClauseKind()) {
+ S.Diag(C->getLocStart(),
+ diag::err_omp_grainsize_num_tasks_mutually_exclusive)
+ << getOpenMPClauseName(C->getClauseKind())
+ << getOpenMPClauseName(PrevClause->getClauseKind());
+ S.Diag(PrevClause->getLocStart(),
+ diag::note_omp_previous_grainsize_num_tasks)
+ << getOpenMPClauseName(PrevClause->getClauseKind());
+ ErrorFound = true;
+ }
+ }
+ }
+ return ErrorFound;
+}
+
+StmtResult Sema::ActOnOpenMPTaskLoopDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
+ /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
+ // OpenMP, [2.9.2 taskloop Construct, Restrictions]
+ // The grainsize clause and num_tasks clause are mutually exclusive and may
+ // not appear on the same taskloop directive.
+ if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
+ NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
+ /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
+ // OpenMP, [2.9.2 taskloop Construct, Restrictions]
+ // The grainsize clause and num_tasks clause are mutually exclusive and may
+ // not appear on the same taskloop directive.
+ if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
+ NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPDistributeDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, AStmt,
+ *this, *DSAStack, VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
+ NestedLoopCount, Clauses, AStmt, B);
}
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
@@ -4576,9 +5625,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation EndLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
- case OMPC_if:
- Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc);
- break;
case OMPC_final:
Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
@@ -4588,9 +5634,37 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_safelen:
Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_simdlen:
+ Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_collapse:
Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_ordered:
+ Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
+ break;
+ case OMPC_device:
+ Res = ActOnOpenMPDeviceClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_num_teams:
+ Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_thread_limit:
+ Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_priority:
+ Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_grainsize:
+ Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_num_tasks:
+ Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_hint:
+ Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_if:
case OMPC_default:
case OMPC_proc_bind:
case OMPC_schedule:
@@ -4603,7 +5677,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
- case OMPC_ordered:
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
@@ -4615,14 +5688,21 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_map:
+ case OMPC_nogroup:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
-OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
+OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
+ Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc,
+ SourceLocation ColonLoc,
SourceLocation EndLoc) {
Expr *ValExpr = Condition;
if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
@@ -4636,7 +5716,8 @@ OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
ValExpr = Val.get();
}
- return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+ return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc,
+ NameModifierLoc, ColonLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
@@ -4701,38 +5782,52 @@ ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
}
+static bool IsNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef,
+ OpenMPClauseKind CKind,
+ bool StrictlyPositive) {
+ if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
+ !ValExpr->isInstantiationDependent()) {
+ SourceLocation Loc = ValExpr->getExprLoc();
+ ExprResult Value =
+ SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
+ if (Value.isInvalid())
+ return false;
+
+ ValExpr = Value.get();
+ // The expression must evaluate to a non-negative integer value.
+ llvm::APSInt Result;
+ if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) &&
+ Result.isSigned() &&
+ !((!StrictlyPositive && Result.isNonNegative()) ||
+ (StrictlyPositive && Result.isStrictlyPositive()))) {
+ SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
+ << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
+ << ValExpr->getSourceRange();
+ return false;
+ }
+ }
+ return true;
+}
+
OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
Expr *ValExpr = NumThreads;
- if (!NumThreads->isValueDependent() && !NumThreads->isTypeDependent() &&
- !NumThreads->containsUnexpandedParameterPack()) {
- SourceLocation NumThreadsLoc = NumThreads->getLocStart();
- ExprResult Val =
- PerformOpenMPImplicitIntegerConversion(NumThreadsLoc, NumThreads);
- if (Val.isInvalid())
- return nullptr;
- ValExpr = Val.get();
-
- // OpenMP [2.5, Restrictions]
- // The num_threads expression must evaluate to a positive integer value.
- llvm::APSInt Result;
- if (ValExpr->isIntegerConstantExpr(Result, Context) && Result.isSigned() &&
- !Result.isStrictlyPositive()) {
- Diag(NumThreadsLoc, diag::err_omp_negative_expression_in_clause)
- << "num_threads" << NumThreads->getSourceRange();
- return nullptr;
- }
- }
+ // OpenMP [2.5, Restrictions]
+ // The num_threads expression must evaluate to a positive integer value.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
+ /*StrictlyPositive=*/true))
+ return nullptr;
return new (Context)
OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc, EndLoc);
}
ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
- OpenMPClauseKind CKind) {
+ OpenMPClauseKind CKind,
+ bool StrictlyPositive) {
if (!E)
return ExprError();
if (E->isValueDependent() || E->isTypeDependent() ||
@@ -4742,9 +5837,11 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);
if (ICE.isInvalid())
return ExprError();
- if (!Result.isStrictlyPositive()) {
+ if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
+ (!StrictlyPositive && !Result.isNonNegative())) {
Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
- << getOpenMPClauseName(CKind) << E->getSourceRange();
+ << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
+ << E->getSourceRange();
return ExprError();
}
if (CKind == OMPC_aligned && !Result.isPowerOf2()) {
@@ -4752,9 +5849,10 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
<< E->getSourceRange();
return ExprError();
}
- if (CKind == OMPC_collapse) {
- DSAStack->setCollapseNumber(Result.getExtValue());
- }
+ if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
+ DSAStack->setAssociatedLoops(Result.getExtValue());
+ else if (CKind == OMPC_ordered)
+ DSAStack->setAssociatedLoops(Result.getExtValue());
return ICE;
}
@@ -4771,6 +5869,19 @@ OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ // OpenMP [2.8.1, simd construct, Description]
+ // The parameter of the simdlen clause must be a constant
+ // positive integer expression.
+ ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
+ if (Simdlen.isInvalid())
+ return nullptr;
+ return new (Context)
+ OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -4788,6 +5899,28 @@ OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ SourceLocation LParenLoc,
+ Expr *NumForLoops) {
+ // OpenMP [2.7.1, loop construct, Description]
+ // OpenMP [2.8.1, simd construct, Description]
+ // OpenMP [2.9.6, distribute construct, Description]
+ // The parameter of the ordered clause must be a constant
+ // positive integer expression if any.
+ if (NumForLoops && LParenLoc.isValid()) {
+ ExprResult NumForLoopsResult =
+ VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
+ if (NumForLoopsResult.isInvalid())
+ return nullptr;
+ NumForLoops = NumForLoopsResult.get();
+ } else
+ NumForLoops = nullptr;
+ DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops);
+ return new (Context)
+ OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPSimpleClause(
OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
@@ -4807,6 +5940,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_schedule:
case OMPC_private:
@@ -4830,39 +5964,58 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_map:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
+static std::string
+getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
+ ArrayRef<unsigned> Exclude = llvm::None) {
+ std::string Values;
+ unsigned Bound = Last >= 2 ? Last - 2 : 0;
+ unsigned Skipped = Exclude.size();
+ auto S = Exclude.begin(), E = Exclude.end();
+ for (unsigned i = First; i < Last; ++i) {
+ if (std::find(S, E, i) != E) {
+ --Skipped;
+ continue;
+ }
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(K, i);
+ Values += "'";
+ if (i == Bound - Skipped)
+ Values += " or ";
+ else if (i != Bound + 1 - Skipped)
+ Values += ", ";
+ }
+ return Values;
+}
+
OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
SourceLocation KindKwLoc,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
if (Kind == OMPC_DEFAULT_unknown) {
- std::string Values;
static_assert(OMPC_DEFAULT_unknown > 0,
"OMPC_DEFAULT_unknown not greater than 0");
- std::string Sep(", ");
- for (unsigned i = 0; i < OMPC_DEFAULT_unknown; ++i) {
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(OMPC_default, i);
- Values += "'";
- switch (i) {
- case OMPC_DEFAULT_unknown - 2:
- Values += " or ";
- break;
- case OMPC_DEFAULT_unknown - 1:
- break;
- default:
- Values += Sep;
- break;
- }
- }
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
- << Values << getOpenMPClauseName(OMPC_default);
+ << getListOfPossibleValues(OMPC_default, /*First=*/0,
+ /*Last=*/OMPC_DEFAULT_unknown)
+ << getOpenMPClauseName(OMPC_default);
return nullptr;
}
switch (Kind) {
@@ -4886,25 +6039,10 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
if (Kind == OMPC_PROC_BIND_unknown) {
- std::string Values;
- std::string Sep(", ");
- for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) {
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i);
- Values += "'";
- switch (i) {
- case OMPC_PROC_BIND_unknown - 2:
- Values += " or ";
- break;
- case OMPC_PROC_BIND_unknown - 1:
- break;
- default:
- Values += Sep;
- break;
- }
- }
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
- << Values << getOpenMPClauseName(OMPC_proc_bind);
+ << getListOfPossibleValues(OMPC_proc_bind, /*First=*/0,
+ /*Last=*/OMPC_PROC_BIND_unknown)
+ << getOpenMPClauseName(OMPC_proc_bind);
return nullptr;
}
return new (Context)
@@ -4912,21 +6050,33 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
}
OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
- OpenMPClauseKind Kind, unsigned Argument, Expr *Expr,
+ OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation ArgumentLoc, SourceLocation CommaLoc,
+ ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
SourceLocation EndLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_schedule:
+ enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
+ assert(Argument.size() == NumberOfElements &&
+ ArgumentLoc.size() == NumberOfElements);
Res = ActOnOpenMPScheduleClause(
- static_cast<OpenMPScheduleClauseKind>(Argument), Expr, StartLoc,
- LParenLoc, ArgumentLoc, CommaLoc, EndLoc);
+ static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
+ static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
+ static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
+ StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
+ ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
break;
case OMPC_if:
+ assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
+ Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
+ Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
+ DelimLoc, EndLoc);
+ break;
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_default:
case OMPC_proc_bind:
@@ -4951,38 +6101,91 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_map:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
+static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
+ OpenMPScheduleClauseModifier M2,
+ SourceLocation M1Loc, SourceLocation M2Loc) {
+ if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
+ SmallVector<unsigned, 2> Excluded;
+ if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
+ Excluded.push_back(M2);
+ if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
+ Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
+ if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
+ Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
+ S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
+ << getListOfPossibleValues(OMPC_schedule,
+ /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
+ /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
+ Excluded)
+ << getOpenMPClauseName(OMPC_schedule);
+ return true;
+ }
+ return false;
+}
+
OMPClause *Sema::ActOnOpenMPScheduleClause(
+ OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
- SourceLocation EndLoc) {
+ SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+ SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
+ if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
+ checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
+ return nullptr;
+ // OpenMP, 2.7.1, Loop Construct, Restrictions
+ // Either the monotonic modifier or the nonmonotonic modifier can be specified
+ // but not both.
+ if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
+ (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
+ M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
+ (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
+ M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
+ Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
+ << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
+ << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
+ return nullptr;
+ }
if (Kind == OMPC_SCHEDULE_unknown) {
std::string Values;
- std::string Sep(", ");
- for (unsigned i = 0; i < OMPC_SCHEDULE_unknown; ++i) {
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(OMPC_schedule, i);
- Values += "'";
- switch (i) {
- case OMPC_SCHEDULE_unknown - 2:
- Values += " or ";
- break;
- case OMPC_SCHEDULE_unknown - 1:
- break;
- default:
- Values += Sep;
- break;
- }
+ if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
+ unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
+ Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
+ /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
+ Exclude);
+ } else {
+ Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
+ /*Last=*/OMPC_SCHEDULE_unknown);
}
Diag(KindLoc, diag::err_omp_unexpected_clause_value)
<< Values << getOpenMPClauseName(OMPC_schedule);
return nullptr;
}
+ // OpenMP, 2.7.1, Loop Construct, Restrictions
+ // The nonmonotonic modifier can only be specified with schedule(dynamic) or
+ // schedule(guided).
+ if ((M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
+ M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
+ Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
+ Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
+ diag::err_omp_schedule_nonmonotonic_static);
+ return nullptr;
+ }
Expr *ValExpr = ChunkSize;
Expr *HelperValExpr = nullptr;
if (ChunkSize) {
@@ -5004,7 +6207,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
if (ValExpr->isIntegerConstantExpr(Result, Context)) {
if (Result.isSigned() && !Result.isStrictlyPositive()) {
Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
- << "schedule" << ChunkSize->getSourceRange();
+ << "schedule" << 1 << ChunkSize->getSourceRange();
return nullptr;
}
} else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
@@ -5018,8 +6221,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
}
}
- return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc,
- EndLoc, Kind, ValExpr, HelperValExpr);
+ return new (Context)
+ OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
+ ValExpr, HelperValExpr, M1, M1Loc, M2, M2Loc);
}
OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
@@ -5054,10 +6258,20 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_seq_cst:
Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
break;
+ case OMPC_threads:
+ Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
+ break;
+ case OMPC_simd:
+ Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
+ break;
+ case OMPC_nogroup:
+ Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_schedule:
case OMPC_private:
@@ -5074,18 +6288,20 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_threadprivate:
case OMPC_flush:
case OMPC_depend:
+ case OMPC_device:
+ case OMPC_map:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_num_tasks:
+ case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
-OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
- SourceLocation EndLoc) {
- DSAStack->setOrderedRegion();
- return new (Context) OMPOrderedClause(StartLoc, EndLoc);
-}
-
OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
SourceLocation EndLoc) {
DSAStack->setNowaitRegion();
@@ -5127,12 +6343,28 @@ OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPThreadsClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPSIMDClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPNogroupClause(StartLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
- SourceLocation DepLoc) {
+ OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType, SourceLocation DepLinMapLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_private:
@@ -5153,7 +6385,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
break;
case OMPC_linear:
Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
- ColonLoc, EndLoc);
+ LinKind, DepLinMapLoc, ColonLoc, EndLoc);
break;
case OMPC_aligned:
Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc,
@@ -5169,13 +6401,18 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_depend:
- Res = ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList, StartLoc,
- LParenLoc, EndLoc);
+ Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList,
+ StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_map:
+ Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, DepLinMapLoc, ColonLoc,
+ VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_default:
case OMPC_proc_bind:
@@ -5190,6 +6427,16 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -5240,16 +6487,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
diag::err_omp_private_incomplete_type)) {
continue;
}
- if (Type->isReferenceType()) {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_private) << Type;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- continue;
- }
+ Type = Type.getNonReferenceType();
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
@@ -5290,7 +6528,8 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// IdResolver, so the code in the OpenMP region uses original variable for
// proper diagnostics.
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName());
+ auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
if (VDPrivate->isInvalidDecl())
continue;
@@ -5384,23 +6623,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
diag::err_omp_firstprivate_incomplete_type)) {
continue;
}
- if (Type->isReferenceType()) {
- if (IsImplicitClause) {
- Diag(ImplicitClauseLoc,
- diag::err_omp_task_predetermined_firstprivate_ref_type_arg)
- << Type;
- Diag(RefExpr->getExprLoc(), diag::note_used_here);
- } else {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_firstprivate) << Type;
- }
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- continue;
- }
+ Type = Type.getNonReferenceType();
// OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
// A variable of class type (or array thereof) that appears in a private
@@ -5492,6 +6715,49 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
}
+
+ // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
+ // A list item that is private within a teams region must not appear in a
+ // firstprivate clause on a distribute construct if any of the distribute
+ // regions arising from the distribute construct ever bind to any of the
+ // teams regions arising from the teams construct.
+ // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
+ // A list item that appears in a reduction clause of a teams construct
+ // must not appear in a firstprivate clause on a distribute construct if
+ // any of the distribute regions arising from the distribute construct
+ // ever bind to any of the teams regions arising from the teams construct.
+ // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
+ // A list item may appear in a firstprivate or lastprivate clause but not
+ // both.
+ if (CurrDir == OMPD_distribute) {
+ DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_private),
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPTeamsDirective(K);
+ },
+ false);
+ if (DVar.CKind == OMPC_private && isOpenMPTeamsDirective(DVar.DKind)) {
+ Diag(ELoc, diag::err_omp_firstprivate_distribute_private_teams);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPTeamsDirective(K);
+ },
+ false);
+ if (DVar.CKind == OMPC_reduction &&
+ isOpenMPTeamsDirective(DVar.DKind)) {
+ Diag(ELoc, diag::err_omp_firstprivate_distribute_in_teams_reduction);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ DVar = DSAStack->getTopDSA(VD, false);
+ if (DVar.CKind == OMPC_lastprivate) {
+ Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
}
// Variably modified types are not supported for tasks.
@@ -5509,7 +6775,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName());
+ auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
// Generate helper private variable and initialize it with the value of the
// original variable. The address of the original variable is replaced by
// the address of the new private variable in the CodeGen. This new variable
@@ -5536,6 +6803,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
VDPrivate->setInvalidDecl();
else
VDPrivate->setInit(Result.getAs<Expr>());
+ // Remove temp variable declaration.
+ Context.Deallocate(VDInitTemp);
} else {
auto *VDInit =
buildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp");
@@ -5618,16 +6887,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
diag::err_omp_lastprivate_incomplete_type)) {
continue;
}
- if (Type->isReferenceType()) {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_lastprivate) << Type;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- continue;
- }
+ Type = Type.getNonReferenceType();
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
@@ -5674,11 +6934,13 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// operator for the class type.
Type = Context.getBaseElementType(Type).getNonReferenceType();
auto *SrcVD = buildVarDecl(*this, DE->getLocStart(),
- Type.getUnqualifiedType(), ".lastprivate.src");
+ Type.getUnqualifiedType(), ".lastprivate.src",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoSrcExpr = buildDeclRefExpr(
*this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc());
auto *DstVD =
- buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst");
+ buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());
// For arrays generate assignment operation for single element and replace
@@ -5692,6 +6954,18 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
if (AssignmentOp.isInvalid())
continue;
+ // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
+ // A list item may appear in a firstprivate or lastprivate clause but not
+ // both.
+ if (CurrDir == OMPD_distribute) {
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+ if (DVar.CKind == OMPC_firstprivate) {
+ Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
+
if (TopDVar.CKind != OMPC_firstprivate)
DSAStack->addDSA(VD, DE, OMPC_lastprivate);
Vars.push_back(DE);
@@ -5879,6 +7153,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
case OO_Call:
case OO_Subscript:
case OO_Conditional:
+ case OO_Coawait:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Unexpected reduction identifier");
case OO_None:
@@ -5903,6 +7178,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
}
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> Privates;
SmallVector<Expr *, 8> LHSs;
SmallVector<Expr *, 8> RHSs;
SmallVector<Expr *, 8> ReductionOps;
@@ -5911,6 +7187,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ Privates.push_back(nullptr);
LHSs.push_back(nullptr);
RHSs.push_back(nullptr);
ReductionOps.push_back(nullptr);
@@ -5922,6 +7199,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
RefExpr->containsUnexpandedParameterPack()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ Privates.push_back(nullptr);
LHSs.push_back(nullptr);
RHSs.push_back(nullptr);
ReductionOps.push_back(nullptr);
@@ -5937,14 +7215,53 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// OpenMP [2.14.3.3, Restrictions, p.1]
// A variable that is part of another variable (as an array or
// structure element) cannot appear in a private clause.
- auto DE = dyn_cast<DeclRefExpr>(RefExpr);
- if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name) << ERange;
+ auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr);
+ auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr);
+ if (!ASE && !OASE && (!DE || !isa<VarDecl>(DE->getDecl()))) {
+ Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) << ERange;
continue;
}
- auto D = DE->getDecl();
- auto VD = cast<VarDecl>(D);
- auto Type = VD->getType();
+ QualType Type;
+ VarDecl *VD = nullptr;
+ if (DE) {
+ auto D = DE->getDecl();
+ VD = cast<VarDecl>(D);
+ Type = VD->getType();
+ } else if (ASE) {
+ Type = ASE->getType();
+ auto *Base = ASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ DE = dyn_cast<DeclRefExpr>(Base);
+ if (DE)
+ VD = dyn_cast<VarDecl>(DE->getDecl());
+ if (!VD) {
+ Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name)
+ << 0 << Base->getSourceRange();
+ continue;
+ }
+ } else if (OASE) {
+ auto BaseType = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
+ if (auto *ATy = BaseType->getAsArrayTypeUnsafe())
+ Type = ATy->getElementType();
+ else
+ Type = BaseType->getPointeeType();
+ auto *Base = OASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
+ Base = TempOASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ DE = dyn_cast<DeclRefExpr>(Base);
+ if (DE)
+ VD = dyn_cast<VarDecl>(DE->getDecl());
+ if (!VD) {
+ Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name)
+ << 1 << Base->getSourceRange();
+ continue;
+ }
+ }
+
// OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
// A variable that appears in a private clause must not have an incomplete
// type or a reference type.
@@ -5955,36 +7272,42 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// Arrays may not appear in a reduction clause.
if (Type.getNonReferenceType()->isArrayType()) {
Diag(ELoc, diag::err_omp_reduction_type_array) << Type << ERange;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (!ASE && !OASE) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
// OpenMP [2.14.3.6, reduction clause, Restrictions]
// A list item that appears in a reduction clause must not be
// const-qualified.
if (Type.getNonReferenceType().isConstant(Context)) {
- Diag(ELoc, diag::err_omp_const_variable)
+ Diag(ELoc, diag::err_omp_const_reduction_list_item)
<< getOpenMPClauseName(OMPC_reduction) << Type << ERange;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (!ASE && !OASE) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
// OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
// If a list-item is a reference type then it must bind to the same object
// for all threads of the team.
- VarDecl *VDDef = VD->getDefinition();
- if (Type->isReferenceType() && VDDef) {
- DSARefChecker Check(DSAStack);
- if (Check.Visit(VDDef->getInit())) {
- Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange;
- Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
- continue;
+ if (!ASE && !OASE) {
+ VarDecl *VDDef = VD->getDefinition();
+ if (Type->isReferenceType() && VDDef) {
+ DSARefChecker Check(DSAStack);
+ if (Check.Visit(VDDef->getInit())) {
+ Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange;
+ Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
+ continue;
+ }
}
}
// OpenMP [2.14.3.6, reduction clause, Restrictions]
@@ -6000,21 +7323,25 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
(getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
<< getLangOpts().CPlusPlus;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (!ASE && !OASE) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
!getLangOpts().CPlusPlus && Type->isFloatingType()) {
Diag(ELoc, diag::err_omp_clause_floating_type_arg);
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (!ASE && !OASE) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -6028,7 +7355,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// Any number of reduction clauses can be specified on the directive,
// but a list item can appear only once in the reduction clauses for that
// directive.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+ DSAStackTy::DSAVarData DVar;
+ DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_reduction) {
Diag(ELoc, diag::err_omp_once_referenced)
<< getOpenMPClauseName(OMPC_reduction);
@@ -6059,9 +7387,27 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
continue;
}
}
+
Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
- auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs");
- auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName());
+ auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ auto PrivateTy = Type;
+ if (OASE) {
+ // For array sections only:
+ // Create pseudo array type for private copy. The size for this array will
+ // be generated during codegen.
+ // For array subscripts or single variables Private Ty is the same as Type
+ // (type of the variable or single array element).
+ PrivateTy = Context.getVariableArrayType(
+ Type, new (Context) OpaqueValueExpr(SourceLocation(),
+ Context.getSizeType(), VK_RValue),
+ ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
+ }
+ // Private copy.
+ auto *PrivateVD = buildVarDecl(*this, ELoc, PrivateTy, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
// Add initializer for private variable.
Expr *Init = nullptr;
switch (BOK) {
@@ -6170,21 +7516,27 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
if (Init) {
AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false,
/*TypeMayContainAuto=*/false);
- } else {
+ } else
ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false);
- }
if (!RHSVD->hasInit()) {
Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
<< ReductionIdRange;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (VD) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
+ // Store initializer for single element in private copy. Will be used during
+ // codegen.
+ PrivateVD->setInit(RHSVD->getInit());
+ PrivateVD->setInitStyle(RHSVD->getInitStyle());
auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc);
auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc);
+ auto *PrivateDRE = buildDeclRefExpr(*this, PrivateVD, PrivateTy, ELoc);
ExprResult ReductionOp =
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
LHSDRE, RHSDRE);
@@ -6201,15 +7553,14 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
BO_Assign, LHSDRE, ConditionalOp);
}
- if (ReductionOp.isUsable()) {
- ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
- }
+ ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
}
if (ReductionOp.isInvalid())
continue;
DSAStack->addDSA(VD, DE, OMPC_reduction);
- Vars.push_back(DE);
+ Vars.push_back(RefExpr);
+ Privates.push_back(PrivateDRE);
LHSs.push_back(LHSDRE);
RHSs.push_back(RHSDRE);
ReductionOps.push_back(ReductionOp.get());
@@ -6220,22 +7571,28 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
return OMPReductionClause::Create(
Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
- ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, LHSs,
- RHSs, ReductionOps);
+ ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates,
+ LHSs, RHSs, ReductionOps);
}
-OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc) {
+OMPClause *Sema::ActOnOpenMPLinearClause(
+ ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
+ SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
+ SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> Privates;
SmallVector<Expr *, 8> Inits;
+ if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
+ LinKind == OMPC_LINEAR_unknown) {
+ Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
+ LinKind = OMPC_LINEAR_val;
+ }
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ Privates.push_back(nullptr);
Inits.push_back(nullptr);
continue;
}
@@ -6278,6 +7635,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
if (QType->isDependentType() || QType->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ Privates.push_back(nullptr);
Inits.push_back(nullptr);
continue;
}
@@ -6287,16 +7645,13 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
diag::err_omp_linear_incomplete_type)) {
continue;
}
- if (QType->isReferenceType()) {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_linear) << QType;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
+ !QType->isReferenceType()) {
+ Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
+ << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
continue;
}
+ QType = QType.getNonReferenceType();
// A list item must not be const-qualified.
if (QType.isConstant(Context)) {
@@ -6324,14 +7679,25 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
continue;
}
+ // Build private copy of original var.
+ auto *Private = buildVarDecl(*this, ELoc, QType, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ auto *PrivateRef = buildDeclRefExpr(
+ *this, Private, DE->getType().getUnqualifiedType(), DE->getExprLoc());
// Build var to save initial value.
VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start");
- AddInitializerToDecl(Init, DefaultLvalueConversion(DE).get(),
+ Expr *InitExpr;
+ if (LinKind == OMPC_LINEAR_uval)
+ InitExpr = VD->getInit();
+ else
+ InitExpr = DE;
+ AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
/*DirectInit*/ false, /*TypeMayContainAuto*/ false);
auto InitRef = buildDeclRefExpr(
*this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc());
DSAStack->addDSA(VD, DE, OMPC_linear);
Vars.push_back(DE);
+ Privates.push_back(PrivateRef);
Inits.push_back(InitRef);
}
@@ -6356,6 +7722,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
ExprResult CalcStep =
BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
+ CalcStep = ActOnFinishFullExpr(CalcStep.get());
// Warn about zero linear step (it would be probably better specified as
// making corresponding variables 'const').
@@ -6371,8 +7738,9 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
}
}
- return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc,
- Vars, Inits, StepExpr, CalcStepExpr);
+ return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
+ ColonLoc, EndLoc, Vars, Privates, Inits,
+ StepExpr, CalcStepExpr);
}
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
@@ -6391,27 +7759,35 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
Step = cast<BinaryOperator>(CalcStep)->getLHS();
bool HasErrors = false;
auto CurInit = Clause.inits().begin();
+ auto CurPrivate = Clause.privates().begin();
+ auto LinKind = Clause.getModifier();
for (auto &RefExpr : Clause.varlists()) {
Expr *InitExpr = *CurInit;
// Build privatized reference to the current linear var.
auto DE = cast<DeclRefExpr>(RefExpr);
- auto PrivateRef =
- buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
- DE->getType().getUnqualifiedType(), DE->getExprLoc(),
- /*RefersToCapture=*/true);
+ Expr *CapturedRef;
+ if (LinKind == OMPC_LINEAR_uval)
+ CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
+ else
+ CapturedRef =
+ buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
+ DE->getType().getUnqualifiedType(), DE->getExprLoc(),
+ /*RefersToCapture=*/true);
// Build update: Var = InitExpr + IV * Step
ExprResult Update =
- BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef,
+ BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,
InitExpr, IV, Step, /* Subtract */ false);
- Update = SemaRef.ActOnFinishFullExpr(Update.get());
+ Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(),
+ /*DiscardedValue=*/true);
// Build final: Var = InitExpr + NumIterations * Step
ExprResult Final =
- BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef,
+ BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,
InitExpr, NumIterations, Step, /* Subtract */ false);
- Final = SemaRef.ActOnFinishFullExpr(Final.get());
+ Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(),
+ /*DiscardedValue=*/true);
if (!Update.isUsable() || !Final.isUsable()) {
Updates.push_back(nullptr);
Finals.push_back(nullptr);
@@ -6420,7 +7796,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
Updates.push_back(Update.get());
Finals.push_back(Final.get());
}
- ++CurInit;
+ ++CurInit, ++CurPrivate;
}
Clause.setUpdates(Updates);
Clause.setFinals(Finals);
@@ -6557,12 +7933,14 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
auto ElemType = Context.getBaseElementType(Type).getNonReferenceType();
- auto *SrcVD = buildVarDecl(*this, DE->getLocStart(),
- ElemType.getUnqualifiedType(), ".copyin.src");
+ auto *SrcVD =
+ buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(),
+ ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoSrcExpr = buildDeclRefExpr(
*this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
auto *DstVD =
- buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst");
+ buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
// For arrays generate assignment operation for single element and replace
@@ -6679,13 +8057,16 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- Type = Context.getBaseElementType(Type).getUnqualifiedType();
+ Type = Context.getBaseElementType(Type.getNonReferenceType())
+ .getUnqualifiedType();
auto *SrcVD =
- buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src");
+ buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoSrcExpr =
buildDeclRefExpr(*this, SrcVD, Type, DE->getExprLoc());
auto *DstVD =
- buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst");
+ buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());
auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
@@ -6727,61 +8108,430 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
SourceLocation DepLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc) {
- if (DepKind == OMPC_DEPEND_unknown) {
- std::string Values;
- std::string Sep(", ");
- for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) {
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i);
- Values += "'";
- switch (i) {
- case OMPC_DEPEND_unknown - 2:
- Values += " or ";
- break;
- case OMPC_DEPEND_unknown - 1:
- break;
- default:
- Values += Sep;
- break;
- }
- }
+ if (DSAStack->getCurrentDirective() == OMPD_ordered &&
+ DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
+ Diag(DepLoc, diag::err_omp_unexpected_clause_value)
+ << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
+ return nullptr;
+ }
+ if (DSAStack->getCurrentDirective() != OMPD_ordered &&
+ (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
+ DepKind == OMPC_DEPEND_sink)) {
+ unsigned Except[] = {OMPC_DEPEND_source, OMPC_DEPEND_sink};
Diag(DepLoc, diag::err_omp_unexpected_clause_value)
- << Values << getOpenMPClauseName(OMPC_depend);
+ << getListOfPossibleValues(OMPC_depend, /*First=*/0,
+ /*Last=*/OMPC_DEPEND_unknown, Except)
+ << getOpenMPClauseName(OMPC_depend);
return nullptr;
}
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP shared clause.");
- if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ llvm::APSInt DepCounter(/*BitWidth=*/32);
+ llvm::APSInt TotalDepCount(/*BitWidth=*/32);
+ if (DepKind == OMPC_DEPEND_sink) {
+ if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
+ TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
+ TotalDepCount.setIsUnsigned(/*Val=*/true);
+ }
+ }
+ if ((DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) ||
+ DSAStack->getParentOrderedRegionParam()) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr) ||
+ (DepKind == OMPC_DEPEND_sink && CurContext->isDependentContext())) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ auto *SimpleExpr = RefExpr->IgnoreParenCasts();
+ if (DepKind == OMPC_DEPEND_sink) {
+ if (DepCounter >= TotalDepCount) {
+ Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
+ continue;
+ }
+ ++DepCounter;
+ // OpenMP [2.13.9, Summary]
+ // depend(dependence-type : vec), where dependence-type is:
+ // 'sink' and where vec is the iteration vector, which has the form:
+ // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
+ // where n is the value specified by the ordered clause in the loop
+ // directive, xi denotes the loop iteration variable of the i-th nested
+ // loop associated with the loop directive, and di is a constant
+ // non-negative integer.
+ SimpleExpr = SimpleExpr->IgnoreImplicit();
+ auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ if (!DE) {
+ OverloadedOperatorKind OOK = OO_None;
+ SourceLocation OOLoc;
+ Expr *LHS, *RHS;
+ if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
+ OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
+ OOLoc = BO->getOperatorLoc();
+ LHS = BO->getLHS()->IgnoreParenImpCasts();
+ RHS = BO->getRHS()->IgnoreParenImpCasts();
+ } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
+ OOK = OCE->getOperator();
+ OOLoc = OCE->getOperatorLoc();
+ LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
+ } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
+ OOK = MCE->getMethodDecl()
+ ->getNameInfo()
+ .getName()
+ .getCXXOverloadedOperator();
+ OOLoc = MCE->getCallee()->getExprLoc();
+ LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
+ RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ } else {
+ Diag(ELoc, diag::err_omp_depend_sink_wrong_expr);
+ continue;
+ }
+ DE = dyn_cast<DeclRefExpr>(LHS);
+ if (!DE) {
+ Diag(LHS->getExprLoc(),
+ diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(
+ DepCounter.getZExtValue());
+ continue;
+ }
+ if (OOK != OO_Plus && OOK != OO_Minus) {
+ Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
+ continue;
+ }
+ ExprResult Res = VerifyPositiveIntegerConstantInClause(
+ RHS, OMPC_depend, /*StrictlyPositive=*/false);
+ if (Res.isInvalid())
+ continue;
+ }
+ auto *VD = dyn_cast<VarDecl>(DE->getDecl());
+ if (!CurContext->isDependentContext() &&
+ DSAStack->getParentOrderedRegionParam() &&
+ (!VD || DepCounter != DSAStack->isParentLoopControlVariable(VD))) {
+ Diag(DE->getExprLoc(),
+ diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(
+ DepCounter.getZExtValue());
+ continue;
+ }
+ } else {
+ // OpenMP [2.11.1.1, Restrictions, p.3]
+ // A variable that is part of another variable (such as a field of a
+ // structure) but is not an array element or an array section cannot
+ // appear in a depend clause.
+ auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
+ (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) ||
+ (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
+ !ASE->getBase()->getType()->isArrayType())) {
+ Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
+ }
+
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ }
+
+ if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
+ TotalDepCount > VarList.size() &&
+ DSAStack->getParentOrderedRegionParam()) {
+ Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
+ }
+ if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
+ Vars.empty())
+ return nullptr;
+ }
+
+ return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind,
+ DepLoc, ColonLoc, Vars);
+}
+
+OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Device;
+
+ // OpenMP [2.9.1, Restrictions]
+ // The device expression must evaluate to a non-negative integer value.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
+ /*StrictlyPositive=*/false))
+ return nullptr;
+
+ return new (Context) OMPDeviceClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+static bool IsCXXRecordForMappable(Sema &SemaRef, SourceLocation Loc,
+ DSAStackTy *Stack, CXXRecordDecl *RD) {
+ if (!RD || RD->isInvalidDecl())
+ return true;
+
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ if (auto *CTD = CTSD->getSpecializedTemplate())
+ RD = CTD->getTemplatedDecl();
+ auto QTy = SemaRef.Context.getRecordType(RD);
+ if (RD->isDynamicClass()) {
+ SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
+ SemaRef.Diag(RD->getLocation(), diag::note_omp_polymorphic_in_target);
+ return false;
+ }
+ auto *DC = RD;
+ bool IsCorrect = true;
+ for (auto *I : DC->decls()) {
+ if (I) {
+ if (auto *MD = dyn_cast<CXXMethodDecl>(I)) {
+ if (MD->isStatic()) {
+ SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
+ SemaRef.Diag(MD->getLocation(),
+ diag::note_omp_static_member_in_target);
+ IsCorrect = false;
+ }
+ } else if (auto *VD = dyn_cast<VarDecl>(I)) {
+ if (VD->isStaticDataMember()) {
+ SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
+ SemaRef.Diag(VD->getLocation(),
+ diag::note_omp_static_member_in_target);
+ IsCorrect = false;
+ }
+ }
+ }
+ }
+
+ for (auto &I : RD->bases()) {
+ if (!IsCXXRecordForMappable(SemaRef, I.getLocStart(), Stack,
+ I.getType()->getAsCXXRecordDecl()))
+ IsCorrect = false;
+ }
+ return IsCorrect;
+}
+
+static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
+ DSAStackTy *Stack, QualType QTy) {
+ NamedDecl *ND;
+ if (QTy->isIncompleteType(&ND)) {
+ SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR;
+ return false;
+ } else if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(ND)) {
+ if (!RD->isInvalidDecl() &&
+ !IsCXXRecordForMappable(SemaRef, SL, Stack, RD))
+ return false;
+ }
+ return true;
+}
+
+OMPClause *Sema::ActOnOpenMPMapClause(
+ OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType,
+ SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
+ SmallVector<Expr *, 4> Vars;
+
+ for (auto &RE : VarList) {
+ assert(RE && "Null expr in omp map");
+ if (isa<DependentScopeDeclRefExpr>(RE)) {
// It will be analyzed later.
- Vars.push_back(RefExpr);
+ Vars.push_back(RE);
continue;
}
+ SourceLocation ELoc = RE->getExprLoc();
- SourceLocation ELoc = RefExpr->getExprLoc();
- // OpenMP [2.11.1.1, Restrictions, p.3]
- // A variable that is part of another variable (such as a field of a
+ // OpenMP [2.14.5, Restrictions]
+ // A variable that is part of another variable (such as field of a
// structure) but is not an array element or an array section cannot appear
- // in a depend clause.
- auto *SimpleExpr = RefExpr->IgnoreParenCasts();
- DeclRefExpr *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
- ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
- if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (!ASE && !DE) ||
+ // in a map clause.
+ auto *VE = RE->IgnoreParenLValueCasts();
+
+ if (VE->isValueDependent() || VE->isTypeDependent() ||
+ VE->isInstantiationDependent() ||
+ VE->containsUnexpandedParameterPack()) {
+ // It will be analyzed later.
+ Vars.push_back(RE);
+ continue;
+ }
+
+ auto *SimpleExpr = RE->IgnoreParenCasts();
+ auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
+
+ if (!RE->IgnoreParenImpCasts()->isLValue() ||
+ (!OASE && !ASE && !DE) ||
(DE && !isa<VarDecl>(DE->getDecl())) ||
(ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
!ASE->getBase()->getType()->isArrayType())) {
Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
- << RefExpr->getSourceRange();
+ << RE->getSourceRange();
continue;
}
- Vars.push_back(RefExpr->IgnoreParenImpCasts());
- }
+ Decl *D = nullptr;
+ if (DE) {
+ D = DE->getDecl();
+ } else if (ASE) {
+ auto *B = ASE->getBase()->IgnoreParenCasts();
+ D = dyn_cast<DeclRefExpr>(B)->getDecl();
+ } else if (OASE) {
+ auto *B = OASE->getBase();
+ D = dyn_cast<DeclRefExpr>(B)->getDecl();
+ }
+ assert(D && "Null decl on map clause.");
+ auto *VD = cast<VarDecl>(D);
+
+ // OpenMP [2.14.5, Restrictions, p.8]
+ // threadprivate variables cannot appear in a map clause.
+ if (DSAStack->isThreadPrivate(VD)) {
+ auto DVar = DSAStack->getTopDSA(VD, false);
+ Diag(ELoc, diag::err_omp_threadprivate_in_map);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+
+ // OpenMP [2.14.5, Restrictions, p.2]
+ // At most one list item can be an array item derived from a given variable
+ // in map clauses of the same construct.
+ // OpenMP [2.14.5, Restrictions, p.3]
+ // List items of map clauses in the same construct must not share original
+ // storage.
+ // OpenMP [2.14.5, Restrictions, C/C++, p.2]
+ // A variable for which the type is pointer, reference to array, or
+ // reference to pointer and an array section derived from that variable
+ // must not appear as list items of map clauses of the same construct.
+ DSAStackTy::MapInfo MI = DSAStack->IsMappedInCurrentRegion(VD);
+ if (MI.RefExpr) {
+ Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc;
+ Diag(MI.RefExpr->getExprLoc(), diag::note_used_here)
+ << MI.RefExpr->getSourceRange();
+ continue;
+ }
+
+ // OpenMP [2.14.5, Restrictions, C/C++, p.3,4]
+ // A variable for which the type is pointer, reference to array, or
+ // reference to pointer must not appear as a list item if the enclosing
+ // device data environment already contains an array section derived from
+ // that variable.
+ // An array section derived from a variable for which the type is pointer,
+ // reference to array, or reference to pointer must not appear as a list
+ // item if the enclosing device data environment already contains that
+ // variable.
+ QualType Type = VD->getType();
+ MI = DSAStack->getMapInfoForVar(VD);
+ if (MI.RefExpr && (isa<DeclRefExpr>(MI.RefExpr->IgnoreParenLValueCasts()) !=
+ isa<DeclRefExpr>(VE)) &&
+ (Type->isPointerType() || Type->isReferenceType())) {
+ Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc;
+ Diag(MI.RefExpr->getExprLoc(), diag::note_used_here)
+ << MI.RefExpr->getSourceRange();
+ continue;
+ }
+ // OpenMP [2.14.5, Restrictions, C/C++, p.7]
+ // A list item must have a mappable type.
+ if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), *this,
+ DSAStack, Type))
+ continue;
+
+ Vars.push_back(RE);
+ MI.RefExpr = RE;
+ DSAStack->addMapInfoForVar(VD, MI);
+ }
if (Vars.empty())
return nullptr;
- return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind,
- DepLoc, ColonLoc, Vars);
+ return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
+ MapTypeModifier, MapType, MapLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = NumTeams;
+
+ // OpenMP [teams Constrcut, Restrictions]
+ // The num_teams expression must evaluate to a positive integer value.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
+ /*StrictlyPositive=*/true))
+ return nullptr;
+
+ return new (Context) OMPNumTeamsClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = ThreadLimit;
+
+ // OpenMP [teams Constrcut, Restrictions]
+ // The thread_limit expression must evaluate to a positive integer value.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
+ /*StrictlyPositive=*/true))
+ return nullptr;
+
+ return new (Context) OMPThreadLimitClause(ValExpr, StartLoc, LParenLoc,
+ EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Priority;
+
+ // OpenMP [2.9.1, task Constrcut]
+ // The priority-value is a non-negative numerical scalar expression.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_priority,
+ /*StrictlyPositive=*/false))
+ return nullptr;
+
+ return new (Context) OMPPriorityClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Grainsize;
+
+ // OpenMP [2.9.2, taskloop Constrcut]
+ // The parameter of the grainsize clause must be a positive integer
+ // expression.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
+ /*StrictlyPositive=*/true))
+ return nullptr;
+
+ return new (Context) OMPGrainsizeClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = NumTasks;
+
+ // OpenMP [2.9.2, taskloop Constrcut]
+ // The parameter of the num_tasks clause must be a positive integer
+ // expression.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks,
+ /*StrictlyPositive=*/true))
+ return nullptr;
+
+ return new (Context) OMPNumTasksClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ // OpenMP [2.13.2, critical construct, Description]
+ // ... where hint-expression is an integer constant expression that evaluates
+ // to a valid lock hint.
+ ExprResult HintExpr = VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint);
+ if (HintExpr.isInvalid())
+ return nullptr;
+ return new (Context)
+ OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 31f581dc15b6..1caa94c9a458 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -38,6 +38,11 @@
using namespace clang;
using namespace sema;
+static bool functionHasPassObjectSizeParams(const FunctionDecl *FD) {
+ return std::any_of(FD->param_begin(), FD->param_end(),
+ std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
+}
+
/// A convenience routine for creating a decayed reference to a function.
static ExprResult
CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
@@ -60,12 +65,8 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
DRE->setHadMultipleCandidates(true);
S.MarkDeclRefReferenced(DRE);
-
- ExprResult E = DRE;
- E = S.DefaultFunctionArrayConversion(E.get());
- if (E.isInvalid())
- return ExprError();
- return E;
+ return S.ImpCastExprToType(DRE, S.Context.getPointerType(DRE->getType()),
+ CK_FunctionToPointerDecay);
}
static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
@@ -88,7 +89,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
static ImplicitConversionSequence::CompareKind
-CompareStandardConversionSequences(Sema &S,
+CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
@@ -98,7 +99,7 @@ CompareQualificationConversions(Sema &S,
const StandardConversionSequence& SCS2);
static ImplicitConversionSequence::CompareKind
-CompareDerivedToBaseConversions(Sema &S,
+CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
@@ -130,7 +131,11 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
ICR_Complex_Real_Conversion,
ICR_Conversion,
ICR_Conversion,
- ICR_Writeback_Conversion
+ ICR_Writeback_Conversion,
+ ICR_Exact_Match, // NOTE(gbiv): This may not be completely right --
+ // it was omitted by the patch that added
+ // ICK_Zero_Event_Conversion
+ ICR_C_Conversion
};
return Rank[(int)Kind];
}
@@ -162,7 +167,9 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"Complex-real conversion",
"Block Pointer conversion",
"Transparent Union Conversion",
- "Writeback conversion"
+ "Writeback conversion",
+ "OpenCL Zero Event Conversion",
+ "C specific type conversion"
};
return Name[Kind];
}
@@ -896,6 +903,11 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl();
}
+ // A using-declaration does not conflict with another declaration
+ // if one of them is hidden.
+ if ((OldIsUsingDecl || NewIsUsingDecl) && !isVisible(*I))
+ continue;
+
// If either declaration was introduced by a using declaration,
// we'll need to use slightly different rules for matching.
// Essentially, these rules are the normal rules, except that
@@ -1051,6 +1063,14 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return true;
}
+ // Though pass_object_size is placed on parameters and takes an argument, we
+ // consider it to be a function-level modifier for the sake of function
+ // identity. Either the function has one or more parameters with
+ // pass_object_size or it doesn't.
+ if (functionHasPassObjectSizeParams(New) !=
+ functionHasPassObjectSizeParams(Old))
+ return true;
+
// enable_if attributes are an order-sensitive part of the signature.
for (specific_attr_iterator<EnableIfAttr>
NewI = New->specific_attr_begin<EnableIfAttr>(),
@@ -1067,6 +1087,25 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return true;
}
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads) {
+ CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New),
+ OldTarget = IdentifyCUDATarget(Old);
+ if (NewTarget == CFT_InvalidTarget || NewTarget == CFT_Global)
+ return false;
+
+ assert((OldTarget != CFT_InvalidTarget) && "Unexpected invalid target.");
+
+ // Don't allow mixing of HD with other kinds. This guarantees that
+ // we have only one viable function with this signature on any
+ // side of CUDA compilation .
+ if ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice))
+ return false;
+
+ // Allow overloading of functions with same signature, but
+ // different CUDA target attributes.
+ return NewTarget != OldTarget;
+ }
+
// The signatures match; this is not an overload.
return false;
}
@@ -1125,7 +1164,8 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
QualType ToCanon
= S.Context.getCanonicalType(ToType).getUnqualifiedType();
if (Constructor->isCopyConstructor() &&
- (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) {
+ (FromCanon == ToCanon ||
+ S.IsDerivedFrom(From->getLocStart(), FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
ICS.setStandard();
@@ -1215,7 +1255,7 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
QualType FromType = From->getType();
if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() &&
(S.Context.hasSameUnqualifiedType(FromType, ToType) ||
- S.IsDerivedFrom(FromType, ToType))) {
+ S.IsDerivedFrom(From->getLocStart(), FromType, ToType))) {
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(FromType);
@@ -1387,7 +1427,7 @@ static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle);
-
+
/// IsStandardConversion - Determines whether there is a standard
/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the
/// expression From to the type ToType. Standard conversion sequences
@@ -1410,13 +1450,10 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
SCS.CopyConstructor = nullptr;
// There are no standard conversions for class types in C++, so
- // abort early. When overloading in C, however, we do permit
- if (FromType->isRecordType() || ToType->isRecordType()) {
- if (S.getLangOpts().CPlusPlus)
- return false;
-
- // When we're overloading in C, we allow, as standard conversions,
- }
+ // abort early. When overloading in C, however, we do permit them.
+ if (S.getLangOpts().CPlusPlus &&
+ (FromType->isRecordType() || ToType->isRecordType()))
+ return false;
// The first conversion can be an lvalue-to-rvalue conversion,
// array-to-pointer conversion, or function-to-pointer conversion
@@ -1521,6 +1558,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Function-to-pointer conversion (C++ 4.3).
SCS.First = ICK_Function_To_Pointer;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(From->IgnoreParenCasts()))
+ if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
+ if (!S.checkAddressOfFunctionIsAvailable(FD))
+ return false;
+
// An lvalue of function type T can be converted to an rvalue of
// type "pointer to T." The result is a pointer to the
// function. (C++ 4.3p1).
@@ -1625,9 +1667,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// tryAtomicConversion has updated the standard conversion sequence
// appropriately.
return true;
- } else if (ToType->isEventT() &&
+ } else if (ToType->isEventT() &&
From->isIntegerConstantExpr(S.getASTContext()) &&
- (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) {
+ From->EvaluateKnownConstInt(S.getASTContext()) == 0) {
SCS.Second = ICK_Zero_Event_Conversion;
FromType = ToType;
} else {
@@ -1666,11 +1708,28 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
}
SCS.setToType(2, FromType);
+ if (CanonFrom == CanonTo)
+ return true;
+
// If we have not converted the argument type to the parameter type,
- // this is a bad conversion sequence.
- if (CanonFrom != CanonTo)
+ // this is a bad conversion sequence, unless we're resolving an overload in C.
+ if (S.getLangOpts().CPlusPlus || !InOverloadResolution)
+ return false;
+
+ ExprResult ER = ExprResult{From};
+ auto Conv = S.CheckSingleAssignmentConstraints(ToType, ER,
+ /*Diagnose=*/false,
+ /*DiagnoseCFAudited=*/false,
+ /*ConvertRHS=*/false);
+ if (Conv != Sema::Compatible)
return false;
+ SCS.setAllToTypes(ToType);
+ // We need to set all three because we want this conversion to rank terribly,
+ // and we don't know what conversions it may overlap with.
+ SCS.First = ICK_C_Only_Conversion;
+ SCS.Second = ICK_C_Only_Conversion;
+ SCS.Third = ICK_C_Only_Conversion;
return true;
}
@@ -1763,7 +1822,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// We have already pre-calculated the promotion type, so this is trivial.
if (ToType->isIntegerType() &&
- !RequireCompleteType(From->getLocStart(), FromType, 0))
+ isCompleteType(From->getLocStart(), FromType))
return Context.hasSameUnqualifiedType(
ToType, FromEnumType->getDecl()->getPromotionType());
}
@@ -2060,7 +2119,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
}
// MSVC allows implicit function to void* type conversion.
- if (getLangOpts().MicrosoftExt && FromPointeeType->isFunctionType() &&
+ if (getLangOpts().MSVCCompat && FromPointeeType->isFunctionType() &&
ToPointeeType->isVoidType()) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
@@ -2094,8 +2153,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
if (getLangOpts().CPlusPlus &&
FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
!Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) &&
- !RequireCompleteType(From->getLocStart(), FromPointeeType, 0) &&
- IsDerivedFrom(FromPointeeType, ToPointeeType)) {
+ IsDerivedFrom(From->getLocStart(), FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
@@ -2467,6 +2525,18 @@ enum {
ft_qualifer_mismatch
};
+/// Attempts to get the FunctionProtoType from a Type. Handles
+/// MemberFunctionPointers properly.
+static const FunctionProtoType *tryGetFunctionProtoType(QualType FromType) {
+ if (auto *FPT = FromType->getAs<FunctionProtoType>())
+ return FPT;
+
+ if (auto *MPT = FromType->getAs<MemberPointerType>())
+ return MPT->getPointeeType()->getAs<FunctionProtoType>();
+
+ return nullptr;
+}
+
/// HandleFunctionTypeMismatch - Gives diagnostic information for differeing
/// function types. Catches different number of parameter, mismatch in
/// parameter types, and different return types.
@@ -2513,8 +2583,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
return;
}
- const FunctionProtoType *FromFunction = FromType->getAs<FunctionProtoType>(),
- *ToFunction = ToType->getAs<FunctionProtoType>();
+ const FunctionProtoType *FromFunction = tryGetFunctionProtoType(FromType),
+ *ToFunction = tryGetFunctionProtoType(ToType);
// Both types need to be function types.
if (!FromFunction || !ToFunction) {
@@ -2621,6 +2691,14 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
// The conversion was successful.
Kind = CK_DerivedToBase;
}
+
+ if (!IsCStyleOrFunctionalCast && FromPointeeType->isFunctionType() &&
+ ToPointeeType->isVoidType()) {
+ assert(getLangOpts().MSVCCompat &&
+ "this should only be possible with MSVCCompat!");
+ Diag(From->getExprLoc(), diag::ext_ms_impcast_fn_obj)
+ << From->getSourceRange();
+ }
}
} else if (const ObjCObjectPointerType *ToPtrType =
ToType->getAs<ObjCObjectPointerType>()) {
@@ -2681,8 +2759,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
QualType ToClass(ToTypePtr->getClass(), 0);
if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
- !RequireCompleteType(From->getLocStart(), ToClass, 0) &&
- IsDerivedFrom(ToClass, FromClass)) {
+ IsDerivedFrom(From->getLocStart(), ToClass, FromClass)) {
ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
ToClass.getTypePtr());
return true;
@@ -2725,7 +2802,8 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths);
+ bool DerivationOkay =
+ IsDerivedFrom(From->getLocStart(), ToClass, FromClass, Paths);
assert(DerivationOkay &&
"Should not have been called if derivation isn't OK.");
(void)DerivationOkay;
@@ -3004,14 +3082,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// the parentheses of the initializer.
if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) ||
(From->getType()->getAs<RecordType>() &&
- S.IsDerivedFrom(From->getType(), ToType)))
+ S.IsDerivedFrom(From->getLocStart(), From->getType(), ToType)))
ConstructorsOnly = true;
- S.RequireCompleteType(From->getExprLoc(), ToType, 0);
- // RequireCompleteType may have returned true due to some invalid decl
- // during template instantiation, but ToType may be complete enough now
- // to try to recover.
- if (ToType->isIncompleteType()) {
+ if (!S.isCompleteType(From->getExprLoc(), ToType)) {
// We're not going to find any constructors.
} else if (CXXRecordDecl *ToRecordDecl
= dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
@@ -3085,7 +3159,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// Enumerate conversion functions, if we're allowed to.
if (ConstructorsOnly || isa<InitListExpr>(From)) {
- } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), 0)) {
+ } else if (!S.isCompleteType(From->getLocStart(), From->getType())) {
// No conversion functions from incomplete types.
} else if (const RecordType *FromRecordType
= From->getType()->getAs<RecordType>()) {
@@ -3212,7 +3286,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
diag::err_typecheck_nonviable_condition_incomplete,
From->getType(), From->getSourceRange()))
Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition)
- << From->getType() << From->getSourceRange() << ToType;
+ << false << From->getType() << From->getSourceRange() << ToType;
} else
return false;
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From);
@@ -3264,7 +3338,7 @@ static bool hasDeprecatedStringLiteralToCharPtrConversion(
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2).
static ImplicitConversionSequence::CompareKind
-CompareImplicitConversionSequences(Sema &S,
+CompareImplicitConversionSequences(Sema &S, SourceLocation Loc,
const ImplicitConversionSequence& ICS1,
const ImplicitConversionSequence& ICS2)
{
@@ -3344,7 +3418,7 @@ CompareImplicitConversionSequences(Sema &S,
if (ICS1.isStandard())
// Standard conversion sequence S1 is a better conversion sequence than
// standard conversion sequence S2 if [...]
- Result = CompareStandardConversionSequences(S,
+ Result = CompareStandardConversionSequences(S, Loc,
ICS1.Standard, ICS2.Standard);
else if (ICS1.isUserDefined()) {
// User-defined conversion sequence U1 is a better conversion
@@ -3355,7 +3429,7 @@ CompareImplicitConversionSequences(Sema &S,
// U2 (C++ 13.3.3.2p3).
if (ICS1.UserDefined.ConversionFunction ==
ICS2.UserDefined.ConversionFunction)
- Result = CompareStandardConversionSequences(S,
+ Result = CompareStandardConversionSequences(S, Loc,
ICS1.UserDefined.After,
ICS2.UserDefined.After);
else
@@ -3453,7 +3527,7 @@ isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2p3).
static ImplicitConversionSequence::CompareKind
-CompareStandardConversionSequences(Sema &S,
+CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2)
{
@@ -3509,7 +3583,7 @@ CompareStandardConversionSequences(Sema &S,
// Neither conversion sequence converts to a void pointer; compare
// their derived-to-base conversions.
if (ImplicitConversionSequence::CompareKind DerivedCK
- = CompareDerivedToBaseConversions(S, SCS1, SCS2))
+ = CompareDerivedToBaseConversions(S, Loc, SCS1, SCS2))
return DerivedCK;
} else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid &&
!S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) {
@@ -3529,9 +3603,9 @@ CompareStandardConversionSequences(Sema &S,
QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType();
QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType();
- if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ else if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
// Objective-C++: If one interface is more specific than the
@@ -3739,7 +3813,7 @@ CompareQualificationConversions(Sema &S,
/// [over.ics.rank]p4b3). As part of these checks, we also look at
/// conversions between Objective-C interface types.
static ImplicitConversionSequence::CompareKind
-CompareDerivedToBaseConversions(Sema &S,
+CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
QualType FromType1 = SCS1.getFromType();
@@ -3782,17 +3856,17 @@ CompareDerivedToBaseConversions(Sema &S,
// -- conversion of C* to B* is better than conversion of C* to A*,
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
- if (S.IsDerivedFrom(ToPointee1, ToPointee2))
+ if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
+ else if (S.IsDerivedFrom(Loc, ToPointee2, ToPointee1))
return ImplicitConversionSequence::Worse;
}
// -- conversion of B* to A* is better than conversion of C* to A*,
if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
- if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ else if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
}
} else if (SCS1.Second == ICK_Pointer_Conversion &&
@@ -3889,16 +3963,16 @@ CompareDerivedToBaseConversions(Sema &S,
QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType();
// conversion of A::* to B::* is better than conversion of A::* to C::*,
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
- if (S.IsDerivedFrom(ToPointee1, ToPointee2))
+ if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2))
return ImplicitConversionSequence::Worse;
- else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
+ else if (S.IsDerivedFrom(Loc, ToPointee2, ToPointee1))
return ImplicitConversionSequence::Better;
}
// conversion of B::* to C::* is better than conversion of A::* to C::*
if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
- if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ else if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Worse;
}
}
@@ -3910,9 +3984,9 @@ CompareDerivedToBaseConversions(Sema &S,
// reference of type A&,
if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
!S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
- if (S.IsDerivedFrom(ToType1, ToType2))
+ if (S.IsDerivedFrom(Loc, ToType1, ToType2))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(ToType2, ToType1))
+ else if (S.IsDerivedFrom(Loc, ToType2, ToType1))
return ImplicitConversionSequence::Worse;
}
@@ -3922,9 +3996,9 @@ CompareDerivedToBaseConversions(Sema &S,
// reference of type A&,
if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
- if (S.IsDerivedFrom(FromType2, FromType1))
+ if (S.IsDerivedFrom(Loc, FromType2, FromType1))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(FromType1, FromType2))
+ else if (S.IsDerivedFrom(Loc, FromType1, FromType2))
return ImplicitConversionSequence::Worse;
}
}
@@ -3973,9 +4047,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
ObjCLifetimeConversion = false;
if (UnqualT1 == UnqualT2) {
// Nothing to do.
- } else if (!RequireCompleteType(Loc, OrigT2, 0) &&
+ } else if (isCompleteType(Loc, OrigT2) &&
isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
- IsDerivedFrom(UnqualT2, UnqualT1))
+ IsDerivedFrom(Loc, UnqualT2, UnqualT1))
DerivedToBase = true;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
UnqualT2->isObjCObjectOrInterfaceType() &&
@@ -4240,7 +4314,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// conversion functions (13.3.1.6) and choosing the best
// one through overload resolution (13.3)),
if (!SuppressUserConversions && T2->isRecordType() &&
- !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ S.isCompleteType(DeclLoc, T2) &&
RefRelationship == Sema::Ref_Incompatible) {
if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
Init, T2, /*AllowRvalues=*/false,
@@ -4303,7 +4377,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// in the second case (or, in either case, to an appropriate base
// class subobject).
if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
- T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ T2->isRecordType() && S.isCompleteType(DeclLoc, T2) &&
FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
Init, T2, /*AllowRvalues=*/true,
AllowExplicit)) {
@@ -4441,7 +4515,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
// We need a complete type for what follows. Incomplete types can never be
// initialized from init lists.
- if (S.RequireCompleteType(From->getLocStart(), ToType, 0))
+ if (!S.isCompleteType(From->getLocStart(), ToType))
return Result;
// Per DR1467:
@@ -4458,7 +4532,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
if (ToType->isRecordType()) {
QualType InitType = From->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
- S.IsDerivedFrom(InitType, ToType))
+ S.IsDerivedFrom(From->getLocStart(), InitType, ToType))
return TryCopyInitialization(S, From->getInit(0), ToType,
SuppressUserConversions,
InOverloadResolution,
@@ -4515,7 +4589,8 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
}
// Otherwise, look for the worst conversion.
if (Result.isBad() ||
- CompareImplicitConversionSequences(S, ICS, Result) ==
+ CompareImplicitConversionSequences(S, From->getLocStart(), ICS,
+ Result) ==
ImplicitConversionSequence::Worse)
Result = ICS;
}
@@ -4722,7 +4797,7 @@ static bool TryCopyInitialization(const CanQualType FromQTy,
/// parameter of the given member function (@c Method) from the
/// expression @p From.
static ImplicitConversionSequence
-TryObjectArgumentInitialization(Sema &S, QualType FromType,
+TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
Expr::Classification FromClassification,
CXXMethodDecl *Method,
CXXRecordDecl *ActingContext) {
@@ -4782,7 +4857,7 @@ TryObjectArgumentInitialization(Sema &S, QualType FromType,
ImplicitConversionKind SecondKind;
if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
SecondKind = ICK_Identity;
- } else if (S.IsDerivedFrom(FromType, ClassType))
+ } else if (S.IsDerivedFrom(Loc, FromType, ClassType))
SecondKind = ICK_Derived_To_Base;
else {
ICS.setBad(BadConversionSequence::unrelated_class,
@@ -4857,7 +4932,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
// Note that we always use the true parent context when performing
// the actual argument initialization.
ImplicitConversionSequence ICS = TryObjectArgumentInitialization(
- *this, From->getType(), FromClassification, Method, Method->getParent());
+ *this, From->getLocStart(), From->getType(), FromClassification, Method,
+ Method->getParent());
if (ICS.isBad()) {
if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
Qualifiers FromQs = FromRecordType.getQualifiers();
@@ -4969,6 +5045,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_TransparentUnionConversion:
case ICK_Writeback_Conversion:
case ICK_Zero_Event_Conversion:
+ case ICK_C_Only_Conversion:
return false;
case ICK_Lvalue_To_Rvalue:
@@ -5372,14 +5449,15 @@ ExprResult Sema::PerformContextualImplicitConversion(
Expr *From;
TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)
- : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {}
+ : Converter(Converter), From(From) {}
void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
}
} IncompleteDiagnoser(Converter, From);
- if (RequireCompleteType(Loc, T, IncompleteDiagnoser))
+ if (Converter.Suppress ? !isCompleteType(Loc, T)
+ : RequireCompleteType(Loc, T, IncompleteDiagnoser))
return From;
// Look for a conversion to an integral or enumeration type.
@@ -5637,10 +5715,10 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// A member function template is never instantiated to perform the copy
// of a class object to an object of its class type.
QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
- if (Args.size() == 1 &&
- Constructor->isSpecializationCopyingObject() &&
+ if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() &&
(Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
- IsDerivedFrom(Args[0]->getType(), ClassType))) {
+ IsDerivedFrom(Args[0]->getLocStart(), Args[0]->getType(),
+ ClassType))) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_illegal_constructor;
return;
@@ -5761,7 +5839,7 @@ ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args,
Match = false;
break;
}
-
+
ImplicitConversionSequence ConversionState
= TryCopyInitialization(*this, argExpr, param->getType(),
/*SuppressUserConversions*/false,
@@ -5809,27 +5887,36 @@ ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args,
return nullptr;
}
-static bool IsNotEnableIfAttr(Attr *A) { return !isa<EnableIfAttr>(A); }
+// specific_attr_iterator iterates over enable_if attributes in reverse, and
+// enable_if is order-sensitive. As a result, we need to reverse things
+// sometimes. Size of 4 elements is arbitrary.
+static SmallVector<EnableIfAttr *, 4>
+getOrderedEnableIfAttrs(const FunctionDecl *Function) {
+ SmallVector<EnableIfAttr *, 4> Result;
+ if (!Function->hasAttrs())
+ return Result;
+
+ const auto &FuncAttrs = Function->getAttrs();
+ for (Attr *Attr : FuncAttrs)
+ if (auto *EnableIf = dyn_cast<EnableIfAttr>(Attr))
+ Result.push_back(EnableIf);
+
+ std::reverse(Result.begin(), Result.end());
+ return Result;
+}
EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
bool MissingImplicitThis) {
- // FIXME: specific_attr_iterator<EnableIfAttr> iterates in reverse order, but
- // we need to find the first failing one.
- if (!Function->hasAttrs())
- return nullptr;
- AttrVec Attrs = Function->getAttrs();
- AttrVec::iterator E = std::remove_if(Attrs.begin(), Attrs.end(),
- IsNotEnableIfAttr);
- if (Attrs.begin() == E)
+ auto EnableIfAttrs = getOrderedEnableIfAttrs(Function);
+ if (EnableIfAttrs.empty())
return nullptr;
- std::reverse(Attrs.begin(), E);
SFINAETrap Trap(*this);
-
- // Convert the arguments.
SmallVector<Expr *, 16> ConvertedArgs;
bool InitializationFailed = false;
bool ContainsValueDependentExpr = false;
+
+ // Convert the arguments.
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
!cast<CXXMethodDecl>(Function)->isStatic() &&
@@ -5861,11 +5948,32 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
}
if (InitializationFailed || Trap.hasErrorOccurred())
- return cast<EnableIfAttr>(Attrs[0]);
+ return EnableIfAttrs[0];
+
+ // Push default arguments if needed.
+ if (!Function->isVariadic() && Args.size() < Function->getNumParams()) {
+ for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) {
+ ParmVarDecl *P = Function->getParamDecl(i);
+ ExprResult R = PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(Context,
+ Function->getParamDecl(i)),
+ SourceLocation(),
+ P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg()
+ : P->getDefaultArg());
+ if (R.isInvalid()) {
+ InitializationFailed = true;
+ break;
+ }
+ ContainsValueDependentExpr |= R.get()->isValueDependent();
+ ConvertedArgs.push_back(R.get());
+ }
+
+ if (InitializationFailed || Trap.hasErrorOccurred())
+ return EnableIfAttrs[0];
+ }
- for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) {
+ for (auto *EIA : EnableIfAttrs) {
APValue Result;
- EnableIfAttr *EIA = cast<EnableIfAttr>(*I);
if (EIA->getCond()->isValueDependent()) {
// Don't even try now, we'll examine it after instantiation.
continue;
@@ -6027,9 +6135,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
else {
// Determine the implicit conversion sequence for the object
// parameter.
- Candidate.Conversions[0]
- = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification,
- Method, ActingContext);
+ Candidate.Conversions[0] = TryObjectArgumentInitialization(
+ *this, CandidateSet.getLocation(), ObjectType, ObjectClassification,
+ Method, ActingContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -6286,10 +6394,9 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
CXXRecordDecl *ConversionContext
= cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
- Candidate.Conversions[0]
- = TryObjectArgumentInitialization(*this, From->getType(),
- From->Classify(Context),
- Conversion, ConversionContext);
+ Candidate.Conversions[0] = TryObjectArgumentInitialization(
+ *this, CandidateSet.getLocation(), From->getType(),
+ From->Classify(Context), Conversion, ConversionContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
@@ -6303,7 +6410,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
QualType FromCanon
= Context.getCanonicalType(From->getType().getUnqualifiedType());
QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
- if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
+ if (FromCanon == ToCanon ||
+ IsDerivedFrom(CandidateSet.getLocation(), FromCanon, ToCanon)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_trivial_conversion;
return;
@@ -6325,7 +6433,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
&ConversionRef, VK_RValue);
QualType ConversionType = Conversion->getConversionType();
- if (RequireCompleteType(From->getLocStart(), ConversionType, 0)) {
+ if (!isCompleteType(From->getLocStart(), ConversionType)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
return;
@@ -6463,10 +6571,9 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
// Determine the implicit conversion sequence for the implicit
// object parameter.
- ImplicitConversionSequence ObjectInit
- = TryObjectArgumentInitialization(*this, Object->getType(),
- Object->Classify(Context),
- Conversion, ActingContext);
+ ImplicitConversionSequence ObjectInit = TryObjectArgumentInitialization(
+ *this, CandidateSet.getLocation(), Object->getType(),
+ Object->Classify(Context), Conversion, ActingContext);
if (ObjectInit.isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -6575,7 +6682,8 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
// the set of member candidates is empty.
if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
// Complete the type if it can be completed.
- RequireCompleteType(OpLoc, T1, 0);
+ if (!isCompleteType(OpLoc, T1) && !T1Rec->isBeingDefined())
+ return;
// If the type is neither complete nor being defined, bail out now.
if (!T1Rec->getDecl()->getDefinition())
return;
@@ -6924,7 +7032,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
HasNullPtrType = true;
} else if (AllowUserConversions && TyRec) {
// No conversion functions in incomplete types.
- if (SemaRef.RequireCompleteType(Loc, Ty, 0))
+ if (!SemaRef.isCompleteType(Loc, Ty))
return;
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
@@ -7527,7 +7635,7 @@ public:
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (int Arg = 0; Arg < 2; ++Arg) {
- QualType AsymetricParamTypes[2] = {
+ QualType AsymmetricParamTypes[2] = {
S.Context.getPointerDiffType(),
S.Context.getPointerDiffType(),
};
@@ -7539,11 +7647,11 @@ public:
if (!PointeeTy->isObjectType())
continue;
- AsymetricParamTypes[Arg] = *Ptr;
+ AsymmetricParamTypes[Arg] = *Ptr;
if (Arg == 0 || Op == OO_Plus) {
// operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
// T* operator+(ptrdiff_t, T*);
- S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, CandidateSet);
+ S.AddBuiltinCandidate(*Ptr, AsymmetricParamTypes, Args, CandidateSet);
}
if (Op == OO_Minus) {
// ptrdiff_t operator-(T, T);
@@ -8013,7 +8121,7 @@ public:
const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
QualType C2 = QualType(mptr->getClass(), 0);
C2 = C2.getUnqualifiedType();
- if (C1 != C2 && !S.IsDerivedFrom(C1, C2))
+ if (C1 != C2 && !S.IsDerivedFrom(CandidateSet.getLocation(), C1, C2))
break;
QualType ParamTypes[2] = { *Ptr, *MemPtr };
// build CV12 T&
@@ -8157,9 +8265,11 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Comma:
case OO_Arrow:
+ case OO_Coawait:
// C++ [over.match.oper]p3:
- // -- For the operator ',', the unary operator '&', or the
- // operator '->', the built-in candidates set is empty.
+ // -- For the operator ',', the unary operator '&', the
+ // operator '->', or the operator 'co_await', the
+ // built-in candidates set is empty.
break;
case OO_Plus: // '+' is either unary or binary
@@ -8328,6 +8438,44 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
}
}
+// Determines whether Cand1 is "better" in terms of its enable_if attrs than
+// Cand2 for overloading. This function assumes that all of the enable_if attrs
+// on Cand1 and Cand2 have conditions that evaluate to true.
+//
+// Cand1's set of enable_if attributes are said to be "better" than Cand2's iff
+// Cand1's first N enable_if attributes have precisely the same conditions as
+// Cand2's first N enable_if attributes (where N = the number of enable_if
+// attributes on Cand2), and Cand1 has more than N enable_if attributes.
+static bool hasBetterEnableIfAttrs(Sema &S, const FunctionDecl *Cand1,
+ const FunctionDecl *Cand2) {
+
+ // FIXME: The next several lines are just
+ // specific_attr_iterator<EnableIfAttr> but going in declaration order,
+ // instead of reverse order which is how they're stored in the AST.
+ auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1);
+ auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2);
+
+ // Candidate 1 is better if it has strictly more attributes and
+ // the common sequence is identical.
+ if (Cand1Attrs.size() <= Cand2Attrs.size())
+ return false;
+
+ auto Cand1I = Cand1Attrs.begin();
+ llvm::FoldingSetNodeID Cand1ID, Cand2ID;
+ for (auto &Cand2A : Cand2Attrs) {
+ Cand1ID.clear();
+ Cand2ID.clear();
+
+ auto &Cand1A = *Cand1I++;
+ Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true);
+ Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true);
+ if (Cand1ID != Cand2ID)
+ return false;
+ }
+
+ return true;
+}
+
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
@@ -8359,7 +8507,7 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
bool HasBetterConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
- switch (CompareImplicitConversionSequences(S,
+ switch (CompareImplicitConversionSequences(S, Loc,
Cand1.Conversions[ArgIdx],
Cand2.Conversions[ArgIdx])) {
case ImplicitConversionSequence::Better:
@@ -8398,7 +8546,7 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
ImplicitConversionSequence::CompareKind Result =
compareConversionFunctions(S, Cand1.Function, Cand2.Function);
if (Result == ImplicitConversionSequence::Indistinguishable)
- Result = CompareStandardConversionSequences(S,
+ Result = CompareStandardConversionSequences(S, Loc,
Cand1.FinalConversion,
Cand2.FinalConversion);
@@ -8438,51 +8586,90 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
// Check for enable_if value-based overload resolution.
if (Cand1.Function && Cand2.Function &&
(Cand1.Function->hasAttr<EnableIfAttr>() ||
- Cand2.Function->hasAttr<EnableIfAttr>())) {
- // FIXME: The next several lines are just
- // specific_attr_iterator<EnableIfAttr> but going in declaration order,
- // instead of reverse order which is how they're stored in the AST.
- AttrVec Cand1Attrs;
- if (Cand1.Function->hasAttrs()) {
- Cand1Attrs = Cand1.Function->getAttrs();
- Cand1Attrs.erase(std::remove_if(Cand1Attrs.begin(), Cand1Attrs.end(),
- IsNotEnableIfAttr),
- Cand1Attrs.end());
- std::reverse(Cand1Attrs.begin(), Cand1Attrs.end());
- }
-
- AttrVec Cand2Attrs;
- if (Cand2.Function->hasAttrs()) {
- Cand2Attrs = Cand2.Function->getAttrs();
- Cand2Attrs.erase(std::remove_if(Cand2Attrs.begin(), Cand2Attrs.end(),
- IsNotEnableIfAttr),
- Cand2Attrs.end());
- std::reverse(Cand2Attrs.begin(), Cand2Attrs.end());
- }
-
- // Candidate 1 is better if it has strictly more attributes and
- // the common sequence is identical.
- if (Cand1Attrs.size() <= Cand2Attrs.size())
- return false;
+ Cand2.Function->hasAttr<EnableIfAttr>()))
+ return hasBetterEnableIfAttrs(S, Cand1.Function, Cand2.Function);
+
+ if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads &&
+ Cand1.Function && Cand2.Function) {
+ FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
+ return S.IdentifyCUDAPreference(Caller, Cand1.Function) >
+ S.IdentifyCUDAPreference(Caller, Cand2.Function);
+ }
+
+ bool HasPS1 = Cand1.Function != nullptr &&
+ functionHasPassObjectSizeParams(Cand1.Function);
+ bool HasPS2 = Cand2.Function != nullptr &&
+ functionHasPassObjectSizeParams(Cand2.Function);
+ return HasPS1 != HasPS2 && HasPS1;
+}
+
+/// Determine whether two declarations are "equivalent" for the purposes of
+/// name lookup and overload resolution. This applies when the same internal/no
+/// linkage entity is defined by two modules (probably by textually including
+/// the same header). In such a case, we don't consider the declarations to
+/// declare the same entity, but we also don't want lookups with both
+/// declarations visible to be ambiguous in some cases (this happens when using
+/// a modularized libstdc++).
+bool Sema::isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
+ const NamedDecl *B) {
+ auto *VA = dyn_cast_or_null<ValueDecl>(A);
+ auto *VB = dyn_cast_or_null<ValueDecl>(B);
+ if (!VA || !VB)
+ return false;
- auto Cand1I = Cand1Attrs.begin();
- for (auto &Cand2A : Cand2Attrs) {
- auto &Cand1A = *Cand1I++;
- llvm::FoldingSetNodeID Cand1ID, Cand2ID;
- cast<EnableIfAttr>(Cand1A)->getCond()->Profile(Cand1ID,
- S.getASTContext(), true);
- cast<EnableIfAttr>(Cand2A)->getCond()->Profile(Cand2ID,
- S.getASTContext(), true);
- if (Cand1ID != Cand2ID)
- return false;
- }
+ // The declarations must be declaring the same name as an internal linkage
+ // entity in different modules.
+ if (!VA->getDeclContext()->getRedeclContext()->Equals(
+ VB->getDeclContext()->getRedeclContext()) ||
+ getOwningModule(const_cast<ValueDecl *>(VA)) ==
+ getOwningModule(const_cast<ValueDecl *>(VB)) ||
+ VA->isExternallyVisible() || VB->isExternallyVisible())
+ return false;
+ // Check that the declarations appear to be equivalent.
+ //
+ // FIXME: Checking the type isn't really enough to resolve the ambiguity.
+ // For constants and functions, we should check the initializer or body is
+ // the same. For non-constant variables, we shouldn't allow it at all.
+ if (Context.hasSameType(VA->getType(), VB->getType()))
return true;
+
+ // Enum constants within unnamed enumerations will have different types, but
+ // may still be similar enough to be interchangeable for our purposes.
+ if (auto *EA = dyn_cast<EnumConstantDecl>(VA)) {
+ if (auto *EB = dyn_cast<EnumConstantDecl>(VB)) {
+ // Only handle anonymous enums. If the enumerations were named and
+ // equivalent, they would have been merged to the same type.
+ auto *EnumA = cast<EnumDecl>(EA->getDeclContext());
+ auto *EnumB = cast<EnumDecl>(EB->getDeclContext());
+ if (EnumA->hasNameForLinkage() || EnumB->hasNameForLinkage() ||
+ !Context.hasSameType(EnumA->getIntegerType(),
+ EnumB->getIntegerType()))
+ return false;
+ // Allow this only if the value is the same for both enumerators.
+ return llvm::APSInt::isSameValue(EA->getInitVal(), EB->getInitVal());
+ }
}
+ // Nothing else is sufficiently similar.
return false;
}
+void Sema::diagnoseEquivalentInternalLinkageDeclarations(
+ SourceLocation Loc, const NamedDecl *D, ArrayRef<const NamedDecl *> Equiv) {
+ Diag(Loc, diag::ext_equivalent_internal_linkage_decl_in_modules) << D;
+
+ Module *M = getOwningModule(const_cast<NamedDecl*>(D));
+ Diag(D->getLocation(), diag::note_equivalent_internal_linkage_decl)
+ << !M << (M ? M->getFullModuleName() : "");
+
+ for (auto *E : Equiv) {
+ Module *M = getOwningModule(const_cast<NamedDecl*>(E));
+ Diag(E->getLocation(), diag::note_equivalent_internal_linkage_decl)
+ << !M << (M ? M->getFullModuleName() : "");
+ }
+}
+
/// \brief Computes the best viable function (C++ 13.3.3)
/// within an overload candidate set.
///
@@ -8510,6 +8697,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
if (Best == end())
return OR_No_Viable_Function;
+ llvm::SmallVector<const NamedDecl *, 4> EquivalentCands;
+
// Make sure that this function is better than every other viable
// function. If not, we have an ambiguity.
for (iterator Cand = begin(); Cand != end(); ++Cand) {
@@ -8517,6 +8706,12 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
Cand != Best &&
!isBetterOverloadCandidate(S, *Best, *Cand, Loc,
UserDefinedConversion)) {
+ if (S.isEquivalentInternalLinkageDeclaration(Best->Function,
+ Cand->Function)) {
+ EquivalentCands.push_back(Cand->Function);
+ continue;
+ }
+
Best = end();
return OR_Ambiguous;
}
@@ -8528,6 +8723,10 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
S.isFunctionConsideredUnavailable(Best->Function)))
return OR_Deleted;
+ if (!EquivalentCands.empty())
+ S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function,
+ EquivalentCands);
+
return OR_Success;
}
@@ -8608,12 +8807,85 @@ void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
} // end anonymous namespace
+static bool isFunctionAlwaysEnabled(const ASTContext &Ctx,
+ const FunctionDecl *FD) {
+ for (auto *EnableIf : FD->specific_attrs<EnableIfAttr>()) {
+ bool AlwaysTrue;
+ if (!EnableIf->getCond()->EvaluateAsBooleanCondition(AlwaysTrue, Ctx))
+ return false;
+ if (!AlwaysTrue)
+ return false;
+ }
+ return true;
+}
+
+/// \brief Returns true if we can take the address of the function.
+///
+/// \param Complain - If true, we'll emit a diagnostic
+/// \param InOverloadResolution - For the purposes of emitting a diagnostic, are
+/// we in overload resolution?
+/// \param Loc - The location of the statement we're complaining about. Ignored
+/// if we're not complaining, or if we're in overload resolution.
+static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
+ bool Complain,
+ bool InOverloadResolution,
+ SourceLocation Loc) {
+ if (!isFunctionAlwaysEnabled(S.Context, FD)) {
+ if (Complain) {
+ if (InOverloadResolution)
+ S.Diag(FD->getLocStart(),
+ diag::note_addrof_ovl_candidate_disabled_by_enable_if_attr);
+ else
+ S.Diag(Loc, diag::err_addrof_function_disabled_by_enable_if_attr) << FD;
+ }
+ return false;
+ }
+
+ auto I = std::find_if(FD->param_begin(), FD->param_end(),
+ std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
+ if (I == FD->param_end())
+ return true;
+
+ if (Complain) {
+ // Add one to ParamNo because it's user-facing
+ unsigned ParamNo = std::distance(FD->param_begin(), I) + 1;
+ if (InOverloadResolution)
+ S.Diag(FD->getLocation(),
+ diag::note_ovl_candidate_has_pass_object_size_params)
+ << ParamNo;
+ else
+ S.Diag(Loc, diag::err_address_of_function_with_pass_object_size_params)
+ << FD << ParamNo;
+ }
+ return false;
+}
+
+static bool checkAddressOfCandidateIsAvailable(Sema &S,
+ const FunctionDecl *FD) {
+ return checkAddressOfFunctionIsAvailable(S, FD, /*Complain=*/true,
+ /*InOverloadResolution=*/true,
+ /*Loc=*/SourceLocation());
+}
+
+bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
+ bool Complain,
+ SourceLocation Loc) {
+ return ::checkAddressOfFunctionIsAvailable(*this, Function, Complain,
+ /*InOverloadResolution=*/false,
+ Loc);
+}
+
// Notes the location of an overload candidate.
-void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) {
+void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType,
+ bool TakingAddress) {
+ if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn))
+ return;
+
std::string FnDesc;
OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
<< (unsigned) K << FnDesc;
+
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
MaybeEmitInheritedConstructorNote(*this, Fn);
@@ -8621,7 +8893,8 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) {
// Notes the location of all overload candidates designated through
// OverloadedExpr
-void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) {
+void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType,
+ bool TakingAddress) {
assert(OverloadedExpr->getType() == Context.OverloadTy);
OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr);
@@ -8632,10 +8905,11 @@ void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) {
I != IEnd; ++I) {
if (FunctionTemplateDecl *FunTmpl =
dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) {
- NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType);
+ NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType,
+ TakingAddress);
} else if (FunctionDecl *Fun
= dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
- NoteOverloadCandidate(Fun, DestType);
+ NoteOverloadCandidate(Fun, DestType, TakingAddress);
}
}
}
@@ -8666,7 +8940,7 @@ void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
}
static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
- unsigned I) {
+ unsigned I, bool TakingCandidateAddress) {
const ImplicitConversionSequence &Conv = Cand->Conversions[I];
assert(Conv.isBad());
assert(Cand->Function && "for now, candidate must be a function");
@@ -8808,7 +9082,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
FromPtrTy->getPointeeType()) &&
!FromPtrTy->getPointeeType()->isIncompleteType() &&
!ToPtrTy->getPointeeType()->isIncompleteType() &&
- S.IsDerivedFrom(ToPtrTy->getPointeeType(),
+ S.IsDerivedFrom(SourceLocation(), ToPtrTy->getPointeeType(),
FromPtrTy->getPointeeType()))
BaseToDerivedConversion = 1;
}
@@ -8826,7 +9100,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) &&
!FromTy->isIncompleteType() &&
!ToRefTy->getPointeeType()->isIncompleteType() &&
- S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) {
+ S.IsDerivedFrom(SourceLocation(), ToRefTy->getPointeeType(), FromTy)) {
BaseToDerivedConversion = 3;
} else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() &&
ToTy.getNonReferenceType().getCanonicalType() ==
@@ -8864,7 +9138,11 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
return;
}
}
-
+
+ if (TakingCandidateAddress &&
+ !checkAddressOfCandidateIsAvailable(S, Cand->Function))
+ return;
+
// Emit the generic diagnostic and, optionally, add the hints to it.
PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv);
FDiag << (unsigned) FnKind << FnDesc
@@ -8975,7 +9253,8 @@ static TemplateDecl *getDescribedTemplate(Decl *Templated) {
/// Diagnose a failed template-argument deduction.
static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
DeductionFailureInfo &DeductionFailure,
- unsigned NumArgs) {
+ unsigned NumArgs,
+ bool TakingCandidateAddress) {
TemplateParameter Param = DeductionFailure.getTemplateParameter();
NamedDecl *ParamD;
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
@@ -9143,6 +9422,11 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
}
}
}
+
+ if (TakingCandidateAddress && isa<FunctionDecl>(Templated) &&
+ !checkAddressOfCandidateIsAvailable(S, cast<FunctionDecl>(Templated)))
+ return;
+
// FIXME: For generic lambda parameters, check if the function is a lambda
// call operator, and if so, emit a prettier and more informative
// diagnostic that mentions 'auto' and lambda in addition to
@@ -9163,14 +9447,15 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
/// Diagnose a failed template-argument deduction, for function calls.
static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
- unsigned NumArgs) {
+ unsigned NumArgs,
+ bool TakingCandidateAddress) {
unsigned TDK = Cand->DeductionFailure.Result;
if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
if (CheckArityMismatch(S, Cand, NumArgs))
return;
}
DiagnoseBadDeduction(S, Cand->Function, // pattern
- Cand->DeductionFailure, NumArgs);
+ Cand->DeductionFailure, NumArgs, TakingCandidateAddress);
}
/// CUDA: diagnose an invalid call across targets.
@@ -9251,7 +9536,8 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
/// more richly for those diagnostic clients that cared, but we'd
/// still have to be just as careful with the default diagnostics.
static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
- unsigned NumArgs) {
+ unsigned NumArgs,
+ bool TakingCandidateAddress) {
FunctionDecl *Fn = Cand->Function;
// Note deleted candidates, but only if they're viable.
@@ -9279,7 +9565,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
return DiagnoseArityMismatch(S, Cand, NumArgs);
case ovl_fail_bad_deduction:
- return DiagnoseBadDeduction(S, Cand, NumArgs);
+ return DiagnoseBadDeduction(S, Cand, NumArgs, TakingCandidateAddress);
case ovl_fail_illegal_constructor: {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_illegal_constructor)
@@ -9297,7 +9583,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
for (unsigned N = Cand->NumConversions; I != N; ++I)
if (Cand->Conversions[I].isBad())
- return DiagnoseBadConversion(S, Cand, I);
+ return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress);
// FIXME: this currently happens when we're called from SemaInit
// when user-conversion overload fails. Figure out how to handle
@@ -9421,9 +9707,10 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
namespace {
struct CompareOverloadCandidatesForDisplay {
Sema &S;
+ SourceLocation Loc;
size_t NumArgs;
- CompareOverloadCandidatesForDisplay(Sema &S, size_t nArgs)
+ CompareOverloadCandidatesForDisplay(Sema &S, SourceLocation Loc, size_t nArgs)
: S(S), NumArgs(nArgs) {}
bool operator()(const OverloadCandidate *L,
@@ -9494,7 +9781,7 @@ struct CompareOverloadCandidatesForDisplay {
int leftBetter = 0;
unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
for (unsigned E = L->NumConversions; I != E; ++I) {
- switch (CompareImplicitConversionSequences(S,
+ switch (CompareImplicitConversionSequences(S, Loc,
L->Conversions[I],
R->Conversions[I])) {
case ImplicitConversionSequence::Better:
@@ -9649,7 +9936,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
}
std::sort(Cands.begin(), Cands.end(),
- CompareOverloadCandidatesForDisplay(S, Args.size()));
+ CompareOverloadCandidatesForDisplay(S, OpLoc, Args.size()));
bool ReportedAmbiguousConversions = false;
@@ -9668,7 +9955,8 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
++CandsShown;
if (Cand->Function)
- NoteFunctionCandidate(S, Cand, Args.size());
+ NoteFunctionCandidate(S, Cand, Args.size(),
+ /*TakingCandidateAddress=*/false);
else if (Cand->IsSurrogate)
NoteSurrogateCandidate(S, Cand);
else {
@@ -9736,9 +10024,10 @@ struct CompareTemplateSpecCandidatesForDisplay {
/// Diagnose a template argument deduction failure.
/// We are treating these failures as overload failures due to bad
/// deductions.
-void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) {
+void TemplateSpecCandidate::NoteDeductionFailure(Sema &S,
+ bool ForTakingAddress) {
DiagnoseBadDeduction(S, Specialization, // pattern
- DeductionFailure, /*NumArgs=*/0);
+ DeductionFailure, /*NumArgs=*/0, ForTakingAddress);
}
void TemplateSpecCandidateSet::destroyCandidates() {
@@ -9791,7 +10080,7 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
assert(Cand->Specialization &&
"Non-matching built-in candidates are not added to Cands.");
- Cand->NoteDeductionFailure(S);
+ Cand->NoteDeductionFailure(S, ForTakingAddress);
}
if (I != E)
@@ -9836,6 +10125,7 @@ class AddressOfFunctionResolver {
bool TargetTypeIsNonStaticMemberFunction;
bool FoundNonTemplateFunction;
bool StaticMemberFunctionFromBoundPointer;
+ bool HasComplained;
OverloadExpr::FindResult OvlExprInfo;
OverloadExpr *OvlExpr;
@@ -9852,9 +10142,10 @@ public:
!!TargetType->getAs<MemberPointerType>()),
FoundNonTemplateFunction(false),
StaticMemberFunctionFromBoundPointer(false),
+ HasComplained(false),
OvlExprInfo(OverloadExpr::find(SourceExpr)),
OvlExpr(OvlExprInfo.Expression),
- FailedCandidates(OvlExpr->getNameLoc()) {
+ FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) {
ExtractUnqualifiedFunctionTypeFromTargetType();
if (TargetFunctionType->isFunctionType()) {
@@ -9885,21 +10176,57 @@ public:
}
if (OvlExpr->hasExplicitTemplateArgs())
- OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
+ OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
if (FindAllFunctionsThatMatchTargetTypeExactly()) {
// C++ [over.over]p4:
// If more than one function is selected, [...]
- if (Matches.size() > 1) {
+ if (Matches.size() > 1 && !eliminiateSuboptimalOverloadCandidates()) {
if (FoundNonTemplateFunction)
EliminateAllTemplateMatches();
else
EliminateAllExceptMostSpecializedTemplate();
}
}
+
+ if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads &&
+ Matches.size() > 1)
+ EliminateSuboptimalCudaMatches();
}
-
+
+ bool hasComplained() const { return HasComplained; }
+
private:
+ // Is A considered a better overload candidate for the desired type than B?
+ bool isBetterCandidate(const FunctionDecl *A, const FunctionDecl *B) {
+ return hasBetterEnableIfAttrs(S, A, B);
+ }
+
+ // Returns true if we've eliminated any (read: all but one) candidates, false
+ // otherwise.
+ bool eliminiateSuboptimalOverloadCandidates() {
+ // Same algorithm as overload resolution -- one pass to pick the "best",
+ // another pass to be sure that nothing is better than the best.
+ auto Best = Matches.begin();
+ for (auto I = Matches.begin()+1, E = Matches.end(); I != E; ++I)
+ if (isBetterCandidate(I->second, Best->second))
+ Best = I;
+
+ const FunctionDecl *BestFn = Best->second;
+ auto IsBestOrInferiorToBest = [this, BestFn](
+ const std::pair<DeclAccessPair, FunctionDecl *> &Pair) {
+ return BestFn == Pair.second || isBetterCandidate(BestFn, Pair.second);
+ };
+
+ // Note: We explicitly leave Matches unmodified if there isn't a clear best
+ // option, so we can potentially give the user a better error
+ if (!std::all_of(Matches.begin(), Matches.end(), IsBestOrInferiorToBest))
+ return false;
+ Matches[0] = *Best;
+ Matches.resize(1);
+ return true;
+ }
+
bool isTargetTypeAFunction() const {
return TargetFunctionType->isFunctionType();
}
@@ -9953,6 +10280,10 @@ private:
assert(S.isSameOrCompatibleFunctionType(
Context.getCanonicalType(Specialization->getType()),
Context.getCanonicalType(TargetFunctionType)));
+
+ if (!S.checkAddressOfFunctionIsAvailable(Specialization))
+ return false;
+
Matches.push_back(std::make_pair(CurAccessFunPair, Specialization));
return true;
}
@@ -9978,16 +10309,22 @@ private:
// now.
if (S.getLangOpts().CPlusPlus14 &&
FunDecl->getReturnType()->isUndeducedType() &&
- S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain))
+ S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) {
+ HasComplained |= Complain;
+ return false;
+ }
+
+ if (!S.checkAddressOfFunctionIsAvailable(FunDecl))
return false;
QualType ResultTy;
if (Context.hasSameUnqualifiedType(TargetFunctionType,
FunDecl->getType()) ||
S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType,
- ResultTy)) {
- Matches.push_back(std::make_pair(CurAccessFunPair,
- cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
+ ResultTy) ||
+ (!S.getLangOpts().CPlusPlus && TargetType->isVoidPointerType())) {
+ Matches.push_back(std::make_pair(
+ CurAccessFunPair, cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
FoundNonTemplateFunction = true;
return true;
}
@@ -10061,7 +10398,8 @@ private:
Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
Matches[0].second = cast<FunctionDecl>(*Result);
Matches.resize(1);
- }
+ } else
+ HasComplained |= Complain;
}
void EliminateAllTemplateMatches() {
@@ -10072,11 +10410,15 @@ private:
++I;
else {
Matches[I] = Matches[--N];
- Matches.set_size(N);
+ Matches.resize(N);
}
}
}
+ void EliminateSuboptimalCudaMatches() {
+ S.EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(S.CurContext), Matches);
+ }
+
public:
void ComplainNoMatchesFound() const {
assert(Matches.empty());
@@ -10084,7 +10426,8 @@ public:
<< OvlExpr->getName() << TargetFunctionType
<< OvlExpr->getSourceRange();
if (FailedCandidates.empty())
- S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
+ S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType,
+ /*TakingAddress=*/true);
else {
// We have some deduction failure messages. Use them to diagnose
// the function templates, and diagnose the non-template candidates
@@ -10094,7 +10437,9 @@ public:
I != IEnd; ++I)
if (FunctionDecl *Fun =
dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
- S.NoteOverloadCandidate(Fun, TargetFunctionType);
+ if (!functionHasPassObjectSizeParams(Fun))
+ S.NoteOverloadCandidate(Fun, TargetFunctionType,
+ /*TakingAddress=*/true);
FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
}
}
@@ -10132,7 +10477,8 @@ public:
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous)
<< OvlExpr->getName()
<< OvlExpr->getSourceRange();
- S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
+ S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType,
+ /*TakingAddress=*/true);
}
bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); }
@@ -10178,13 +10524,14 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
Complain);
int NumMatches = Resolver.getNumMatches();
FunctionDecl *Fn = nullptr;
- if (NumMatches == 0 && Complain) {
+ bool ShouldComplain = Complain && !Resolver.hasComplained();
+ if (NumMatches == 0 && ShouldComplain) {
if (Resolver.IsInvalidFormOfPointerToMemberFunction())
Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
else
Resolver.ComplainNoMatchesFound();
}
- else if (NumMatches > 1 && Complain)
+ else if (NumMatches > 1 && ShouldComplain)
Resolver.ComplainMultipleMatchesFound();
else if (NumMatches == 1) {
Fn = Resolver.getMatchingFunctionDecl();
@@ -10229,7 +10576,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
return nullptr;
TemplateArgumentListInfo ExplicitTemplateArgs;
- ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+ ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
// Look through all of the overloaded functions, searching for one
@@ -10303,7 +10650,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// returns true if 'complain' is set.
bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
ExprResult &SrcExpr, bool doFunctionPointerConverion,
- bool complain, const SourceRange& OpRangeForComplaining,
+ bool complain, SourceRange OpRangeForComplaining,
QualType DestTypeForComplaining,
unsigned DiagIDForComplaining) {
assert(SrcExpr.get()->getType() == Context.OverloadTy);
@@ -10678,8 +11025,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
// casts and such from the call, we don't really care.
ExprResult NewFn = ExprError();
if ((*R.begin())->isCXXClassMember())
- NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
- R, ExplicitTemplateArgs);
+ NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R,
+ ExplicitTemplateArgs, S);
else if (ExplicitTemplateArgs || TemplateKWLoc.isValid())
NewFn = SemaRef.BuildTemplateIdExpr(SS, TemplateKWLoc, R, false,
ExplicitTemplateArgs);
@@ -10749,6 +11096,8 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
CallExpr *CE = new (Context) CallExpr(
Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc);
CE->setTypeDependent(true);
+ CE->setValueDependent(true);
+ CE->setInstantiationDependent(true);
*Result = CE;
return true;
}
@@ -10800,9 +11149,23 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
if (!Recovery.isInvalid())
return Recovery;
- SemaRef.Diag(Fn->getLocStart(),
- diag::err_ovl_no_viable_function_in_call)
- << ULE->getName() << Fn->getSourceRange();
+ // If the user passes in a function that we can't take the address of, we
+ // generally end up emitting really bad error messages. Here, we attempt to
+ // emit better ones.
+ for (const Expr *Arg : Args) {
+ if (!Arg->getType()->isFunctionType())
+ continue;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts())) {
+ auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (FD &&
+ !SemaRef.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+ Arg->getExprLoc()))
+ return ExprError();
+ }
+ }
+
+ SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_no_viable_function_in_call)
+ << ULE->getName() << Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
break;
}
@@ -10875,8 +11238,7 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
///
/// \param OpLoc The location of the operator itself (e.g., '*').
///
-/// \param OpcIn The UnaryOperator::Opcode that describes this
-/// operator.
+/// \param Opc The UnaryOperatorKind that describes this operator.
///
/// \param Fns The set of non-member functions that will be
/// considered by overload resolution. The caller needs to build this
@@ -10887,11 +11249,9 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
///
/// \param Input The input argument.
ExprResult
-Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
Expr *Input) {
- UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
-
OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc);
assert(Op != OO_None && "Invalid opcode for overloaded unary operator");
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
@@ -11062,8 +11422,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
///
/// \param OpLoc The location of the operator itself (e.g., '+').
///
-/// \param OpcIn The BinaryOperator::Opcode that describes this
-/// operator.
+/// \param Opc The BinaryOperatorKind that describes this operator.
///
/// \param Fns The set of non-member functions that will be
/// considered by overload resolution. The caller needs to build this
@@ -11076,13 +11435,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
/// \param RHS Right-hand argument.
ExprResult
Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
- unsigned OpcIn,
+ BinaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS) {
Expr *Args[2] = { LHS, RHS };
LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple
- BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
@@ -11565,10 +11923,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
- if (resultType->isMemberPointerType())
- if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- RequireCompleteType(LParenLoc, resultType, 0);
-
CXXMemberCallExpr *call
= new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
resultType, valueKind, RParenLoc);
@@ -11767,18 +12121,39 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
if (CheckFunctionCall(Method, TheCall, Proto))
return ExprError();
+ // In the case the method to call was not selected by the overloading
+ // resolution process, we still need to handle the enable_if attribute. Do
+ // that here, so it will not hide previous -- and more relevant -- errors
+ if (isa<MemberExpr>(NakedMemExpr)) {
+ if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) {
+ Diag(MemExprE->getLocStart(),
+ diag::err_ovl_no_viable_member_function_in_call)
+ << Method << Method->getSourceRange();
+ Diag(Method->getLocation(),
+ diag::note_ovl_candidate_disabled_by_enable_if_attr)
+ << Attr->getCond()->getSourceRange() << Attr->getMessage();
+ return ExprError();
+ }
+ }
+
if ((isa<CXXConstructorDecl>(CurContext) ||
isa<CXXDestructorDecl>(CurContext)) &&
TheCall->getMethodDecl()->isPure()) {
const CXXMethodDecl *MD = TheCall->getMethodDecl();
- if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts())) {
- Diag(MemExpr->getLocStart(),
+ if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts()) &&
+ MemExpr->performsVirtualDispatch(getLangOpts())) {
+ Diag(MemExpr->getLocStart(),
diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor)
<< MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
<< MD->getParent()->getDeclName();
Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName();
+ if (getLangOpts().AppleKext)
+ Diag(MemExpr->getLocStart(),
+ diag::note_pure_qualified_call_kext)
+ << MD->getParent()->getDeclName()
+ << MD->getDeclName();
}
}
return MaybeBindToTemporary(TheCall);
@@ -12267,13 +12642,14 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
/// otherwise CallExpr is set to ExprError() and some non-success value
/// is returned.
Sema::ForRangeStatus
-Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
- SourceLocation RangeLoc, VarDecl *Decl,
- BeginEndFunction BEF,
+Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
+ SourceLocation RangeLoc,
const DeclarationNameInfo &NameInfo,
LookupResult &MemberLookup,
OverloadCandidateSet *CandidateSet,
Expr *Range, ExprResult *CallExpr) {
+ Scope *S = nullptr;
+
CandidateSet->clear();
if (!MemberLookup.empty()) {
ExprResult MemberRef =
@@ -12282,18 +12658,14 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
/*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
MemberLookup,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr, S);
if (MemberRef.isInvalid()) {
*CallExpr = ExprError();
- Diag(Range->getLocStart(), diag::note_in_for_range)
- << RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
*CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, None, Loc, nullptr);
if (CallExpr->isInvalid()) {
*CallExpr = ExprError();
- Diag(Range->getLocStart(), diag::note_in_for_range)
- << RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
} else {
@@ -12324,8 +12696,6 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
/*AllowTypoCorrection=*/false);
if (CallExpr->isInvalid() || OverloadResult != OR_Success) {
*CallExpr = ExprError();
- Diag(Range->getLocStart(), diag::note_in_for_range)
- << RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
}
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index fec97488f531..e5d51f173caa 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -44,17 +44,76 @@ using namespace sema;
namespace {
// Basically just a very focused copy of TreeTransform.
- template <class T> struct Rebuilder {
+ struct Rebuilder {
Sema &S;
- Rebuilder(Sema &S) : S(S) {}
+ unsigned MSPropertySubscriptCount;
+ typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy;
+ const SpecificRebuilderRefTy &SpecificCallback;
+ Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback)
+ : S(S), MSPropertySubscriptCount(0),
+ SpecificCallback(SpecificCallback) {}
+
+ Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) {
+ // Fortunately, the constraint that we're rebuilding something
+ // with a base limits the number of cases here.
+ if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
+ return refExpr;
+
+ if (refExpr->isExplicitProperty()) {
+ return new (S.Context) ObjCPropertyRefExpr(
+ refExpr->getExplicitProperty(), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getObjectKind(),
+ refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
+ }
+ return new (S.Context) ObjCPropertyRefExpr(
+ refExpr->getImplicitPropertyGetter(),
+ refExpr->getImplicitPropertySetter(), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getObjectKind(),
+ refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
+ }
+ Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) {
+ assert(refExpr->getBaseExpr());
+ assert(refExpr->getKeyExpr());
+
+ return new (S.Context) ObjCSubscriptRefExpr(
+ SpecificCallback(refExpr->getBaseExpr(), 0),
+ SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getObjectKind(),
+ refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(),
+ refExpr->getRBracket());
+ }
+ Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) {
+ assert(refExpr->getBaseExpr());
- T &getDerived() { return static_cast<T&>(*this); }
+ return new (S.Context) MSPropertyRefExpr(
+ SpecificCallback(refExpr->getBaseExpr(), 0),
+ refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getQualifierLoc(),
+ refExpr->getMemberLoc());
+ }
+ Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) {
+ assert(refExpr->getBase());
+ assert(refExpr->getIdx());
+
+ auto *NewBase = rebuild(refExpr->getBase());
+ ++MSPropertySubscriptCount;
+ return new (S.Context) MSPropertySubscriptExpr(
+ NewBase,
+ SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount),
+ refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(),
+ refExpr->getRBracketLoc());
+ }
Expr *rebuild(Expr *e) {
// Fast path: nothing to look through.
- if (typename T::specific_type *specific
- = dyn_cast<typename T::specific_type>(e))
- return getDerived().rebuildSpecific(specific);
+ if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e))
+ return rebuildObjCPropertyRefExpr(PRE);
+ if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e))
+ return rebuildObjCSubscriptRefExpr(SRE);
+ if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e))
+ return rebuildMSPropertyRefExpr(MSPRE);
+ if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e))
+ return rebuildMSPropertySubscriptExpr(MSPSE);
// Otherwise, we should look through and rebuild anything that
// IgnoreParens would.
@@ -125,72 +184,6 @@ namespace {
}
};
- struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
- Expr *NewBase;
- ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
- : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {}
-
- typedef ObjCPropertyRefExpr specific_type;
- Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
- // Fortunately, the constraint that we're rebuilding something
- // with a base limits the number of cases here.
- assert(refExpr->isObjectReceiver());
-
- if (refExpr->isExplicitProperty()) {
- return new (S.Context)
- ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
- refExpr->getType(), refExpr->getValueKind(),
- refExpr->getObjectKind(), refExpr->getLocation(),
- NewBase);
- }
- return new (S.Context)
- ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
- refExpr->getImplicitPropertySetter(),
- refExpr->getType(), refExpr->getValueKind(),
- refExpr->getObjectKind(),refExpr->getLocation(),
- NewBase);
- }
- };
-
- struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> {
- Expr *NewBase;
- Expr *NewKeyExpr;
- ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr)
- : Rebuilder<ObjCSubscriptRefRebuilder>(S),
- NewBase(newBase), NewKeyExpr(newKeyExpr) {}
-
- typedef ObjCSubscriptRefExpr specific_type;
- Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) {
- assert(refExpr->getBaseExpr());
- assert(refExpr->getKeyExpr());
-
- return new (S.Context)
- ObjCSubscriptRefExpr(NewBase,
- NewKeyExpr,
- refExpr->getType(), refExpr->getValueKind(),
- refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(),
- refExpr->setAtIndexMethodDecl(),
- refExpr->getRBracket());
- }
- };
-
- struct MSPropertyRefRebuilder : Rebuilder<MSPropertyRefRebuilder> {
- Expr *NewBase;
- MSPropertyRefRebuilder(Sema &S, Expr *newBase)
- : Rebuilder<MSPropertyRefRebuilder>(S), NewBase(newBase) {}
-
- typedef MSPropertyRefExpr specific_type;
- Expr *rebuildSpecific(MSPropertyRefExpr *refExpr) {
- assert(refExpr->getBaseExpr());
-
- return new (S.Context)
- MSPropertyRefExpr(NewBase, refExpr->getPropertyDecl(),
- refExpr->isArrow(), refExpr->getType(),
- refExpr->getValueKind(), refExpr->getQualifierLoc(),
- refExpr->getMemberLoc());
- }
- };
-
class PseudoOpBuilder {
public:
Sema &S;
@@ -236,7 +229,7 @@ namespace {
}
/// Return true if assignments have a non-void result.
- bool CanCaptureValue(Expr *exp) {
+ static bool CanCaptureValue(Expr *exp) {
if (exp->isGLValue())
return true;
QualType ty = exp->getType();
@@ -252,6 +245,20 @@ namespace {
virtual ExprResult buildGet() = 0;
virtual ExprResult buildSet(Expr *, SourceLocation,
bool captureSetValueAsResult) = 0;
+ /// \brief Should the result of an assignment be the formal result of the
+ /// setter call or the value that was passed to the setter?
+ ///
+ /// Different pseudo-object language features use different language rules
+ /// for this.
+ /// The default is to use the set value. Currently, this affects the
+ /// behavior of simple assignments, compound assignments, and prefix
+ /// increment and decrement.
+ /// Postfix increment and decrement always use the getter result as the
+ /// expression result.
+ ///
+ /// If this method returns true, and the set value isn't capturable for
+ /// some reason, the result of the expression will be void.
+ virtual bool captureSetValueAsResult() const { return true; }
};
/// A PseudoOpBuilder for Objective-C \@properties.
@@ -328,15 +335,25 @@ namespace {
class MSPropertyOpBuilder : public PseudoOpBuilder {
MSPropertyRefExpr *RefExpr;
+ OpaqueValueExpr *InstanceBase;
+ SmallVector<Expr *, 4> CallArgs;
+
+ MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
public:
MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
- RefExpr(refExpr) {}
+ RefExpr(refExpr), InstanceBase(nullptr) {}
+ MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+ InstanceBase(nullptr) {
+ RefExpr = getBaseMSProperty(refExpr);
+ }
Expr *rebuildAndCaptureObject(Expr *) override;
ExprResult buildGet() override;
ExprResult buildSet(Expr *op, SourceLocation, bool) override;
+ bool captureSetValueAsResult() const override { return false; }
};
}
@@ -406,19 +423,27 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
BinaryOperatorKind opcode,
Expr *LHS, Expr *RHS) {
assert(BinaryOperator::isAssignmentOp(opcode));
-
- // Recover from user error
- if (isa<UnresolvedLookupExpr>(RHS))
- return ExprError();
Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
OpaqueValueExpr *capturedRHS = capture(RHS);
+ // In some very specific cases, semantic analysis of the RHS as an
+ // expression may require it to be rewritten. In these cases, we
+ // cannot safely keep the OVE around. Fortunately, we don't really
+ // need to: we don't use this particular OVE in multiple places, and
+ // no clients rely that closely on matching up expressions in the
+ // semantic expression with expressions from the syntactic form.
+ Expr *semanticRHS = capturedRHS;
+ if (RHS->hasPlaceholderType() || isa<InitListExpr>(RHS)) {
+ semanticRHS = RHS;
+ Semantics.pop_back();
+ }
+
Expr *syntactic;
ExprResult result;
if (opcode == BO_Assign) {
- result = capturedRHS;
+ result = semanticRHS;
syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
opcode, capturedRHS->getType(),
capturedRHS->getValueKind(),
@@ -430,8 +455,7 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
// Build an ordinary, non-compound operation.
BinaryOperatorKind nonCompound =
BinaryOperator::getOpForCompoundAssignment(opcode);
- result = S.BuildBinOp(Sc, opcLoc, nonCompound,
- opLHS.get(), capturedRHS);
+ result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS);
if (result.isInvalid()) return ExprError();
syntactic =
@@ -446,9 +470,12 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
// The result of the assignment, if not void, is the value set into
// the l-value.
- result = buildSet(result.get(), opcLoc, /*captureSetValueAsResult*/ true);
+ result = buildSet(result.get(), opcLoc, captureSetValueAsResult());
if (result.isInvalid()) return ExprError();
addSemanticExpr(result.get());
+ if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() &&
+ (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
+ setResultToLastSemantic();
return complete(syntactic);
}
@@ -490,9 +517,14 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
// Store that back into the result. The value stored is the result
// of a prefix operation.
- result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode));
+ result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) &&
+ captureSetValueAsResult());
if (result.isInvalid()) return ExprError();
addSemanticExpr(result.get());
+ if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() &&
+ !result.get()->getType()->isVoidType() &&
+ (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
+ setResultToLastSemantic();
UnaryOperator *syntactic =
new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
@@ -666,9 +698,9 @@ Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
// form to use the OVE as its base.
if (RefExpr->isObjectReceiver()) {
InstanceReceiver = capture(RefExpr->getBase());
-
- syntacticBase =
- ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
+ syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {
+ return InstanceReceiver;
+ }).rebuild(syntacticBase);
}
if (ObjCPropertyRefExpr *
@@ -745,16 +777,6 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
op = opResult.get();
assert(op && "successful assignment left argument invalid?");
}
- else if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(op)) {
- Expr *Initializer = OVE->getSourceExpr();
- // passing C++11 style initialized temporaries to objc++ properties
- // requires special treatment by removing OpaqueValueExpr so type
- // conversion takes place and adding the OpaqueValueExpr later on.
- if (isa<InitListExpr>(Initializer) &&
- Initializer->getType()->isVoidType()) {
- op = Initializer;
- }
- }
}
// Arguments.
@@ -996,11 +1018,19 @@ Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
// form to use the OVE as its base expression.
InstanceBase = capture(RefExpr->getBaseExpr());
InstanceKey = capture(RefExpr->getKeyExpr());
-
+
syntacticBase =
- ObjCSubscriptRefRebuilder(S, InstanceBase,
- InstanceKey).rebuild(syntacticBase);
-
+ Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
+ switch (Idx) {
+ case 0:
+ return InstanceBase;
+ case 1:
+ return InstanceKey;
+ default:
+ llvm_unreachable("Unexpected index for ObjCSubscriptExpr");
+ }
+ }).rebuild(syntacticBase);
+
return syntacticBase;
}
@@ -1402,11 +1432,30 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
// MSVC __declspec(property) references
//===----------------------------------------------------------------------===//
-Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
- Expr *NewBase = capture(RefExpr->getBaseExpr());
+MSPropertyRefExpr *
+MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {
+ CallArgs.insert(CallArgs.begin(), E->getIdx());
+ Expr *Base = E->getBase()->IgnoreParens();
+ while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {
+ CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());
+ Base = MSPropSubscript->getBase()->IgnoreParens();
+ }
+ return cast<MSPropertyRefExpr>(Base);
+}
- syntacticBase =
- MSPropertyRefRebuilder(S, NewBase).rebuild(syntacticBase);
+Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
+ InstanceBase = capture(RefExpr->getBaseExpr());
+ std::for_each(CallArgs.begin(), CallArgs.end(),
+ [this](Expr *&Arg) { Arg = capture(Arg); });
+ syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
+ switch (Idx) {
+ case 0:
+ return InstanceBase;
+ default:
+ assert(Idx <= CallArgs.size());
+ return CallArgs[Idx - 1];
+ }
+ }).rebuild(syntacticBase);
return syntacticBase;
}
@@ -1423,10 +1472,10 @@ ExprResult MSPropertyOpBuilder::buildGet() {
GetterName.setIdentifier(II, RefExpr->getMemberLoc());
CXXScopeSpec SS;
SS.Adopt(RefExpr->getQualifierLoc());
- ExprResult GetterExpr = S.ActOnMemberAccessExpr(
- S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
- RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- GetterName, nullptr);
+ ExprResult GetterExpr =
+ S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
+ RefExpr->isArrow() ? tok::arrow : tok::period, SS,
+ SourceLocation(), GetterName, nullptr);
if (GetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::error_cannot_find_suitable_accessor) << 0 /* getter */
@@ -1434,9 +1483,8 @@ ExprResult MSPropertyOpBuilder::buildGet() {
return ExprError();
}
- MultiExprArg ArgExprs;
return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(),
- RefExpr->getSourceRange().getBegin(), ArgExprs,
+ RefExpr->getSourceRange().getBegin(), CallArgs,
RefExpr->getSourceRange().getEnd());
}
@@ -1453,10 +1501,10 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
SetterName.setIdentifier(II, RefExpr->getMemberLoc());
CXXScopeSpec SS;
SS.Adopt(RefExpr->getQualifierLoc());
- ExprResult SetterExpr = S.ActOnMemberAccessExpr(
- S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
- RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- SetterName, nullptr);
+ ExprResult SetterExpr =
+ S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
+ RefExpr->isArrow() ? tok::arrow : tok::period, SS,
+ SourceLocation(), SetterName, nullptr);
if (SetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::error_cannot_find_suitable_accessor) << 1 /* setter */
@@ -1464,7 +1512,8 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
return ExprError();
}
- SmallVector<Expr*, 1> ArgExprs;
+ SmallVector<Expr*, 4> ArgExprs;
+ ArgExprs.append(CallArgs.begin(), CallArgs.end());
ArgExprs.push_back(op);
return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(),
RefExpr->getSourceRange().getBegin(), ArgExprs,
@@ -1490,6 +1539,10 @@ ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
MSPropertyOpBuilder builder(*this, refExpr);
return builder.buildRValueOperation(E);
+ } else if (MSPropertySubscriptExpr *RefExpr =
+ dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+ MSPropertyOpBuilder Builder(*this, RefExpr);
+ return Builder.buildRValueOperation(E);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1516,6 +1569,10 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
MSPropertyOpBuilder builder(*this, refExpr);
return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
+ } else if (MSPropertySubscriptExpr *RefExpr
+ = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+ MSPropertyOpBuilder Builder(*this, RefExpr);
+ return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1547,8 +1604,12 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
- return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+ MSPropertyOpBuilder builder(*this, refExpr);
+ return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+ } else if (MSPropertySubscriptExpr *RefExpr
+ = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+ MSPropertyOpBuilder Builder(*this, RefExpr);
+ return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1558,29 +1619,11 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
/// values. Basically, undo the behavior of rebuildAndCaptureObject.
/// This should never operate in-place.
static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
- Expr *opaqueRef = E->IgnoreParens();
- if (ObjCPropertyRefExpr *refExpr
- = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- // Class and super property references don't have opaque values in them.
- if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
- return E;
-
- assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
- OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
- return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
- } else if (ObjCSubscriptRefExpr *refExpr
- = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
- OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
- OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
- return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
- keyOVE->getSourceExpr()).rebuild(E);
- } else if (MSPropertyRefExpr *refExpr
- = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
- return MSPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
- } else {
- llvm_unreachable("unknown pseudo-object kind!");
- }
+ return Rebuilder(S,
+ [=](Expr *E, unsigned) -> Expr * {
+ return cast<OpaqueValueExpr>(E)->getSourceExpr();
+ })
+ .rebuild(E);
}
/// Given a pseudo-object expression, recreate what it looks like
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index c4f6fd8df1c4..e1b1a47e182b 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -195,7 +195,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (isUnevaluatedContext())
return;
- SourceLocation ExprLoc = E->IgnoreParens()->getExprLoc();
+ SourceLocation ExprLoc = E->IgnoreParenImpCasts()->getExprLoc();
// In most cases, we don't want to warn if the expression is written in a
// macro body, or if the macro comes from a system header. If the offending
// expression is a call to a function with the warn_unused_result attribute,
@@ -218,6 +218,15 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (isa<StmtExpr>(E) && Loc.isMacroID())
return;
+ // Check if this is the UNREFERENCED_PARAMETER from the Microsoft headers.
+ // That macro is frequently used to suppress "unused parameter" warnings,
+ // but its implementation makes clang's -Wunused-value fire. Prevent this.
+ if (isa<ParenExpr>(E->IgnoreImpCasts()) && Loc.isMacroID()) {
+ SourceLocation SpellLoc = Loc;
+ if (findMacroSpelling(SpellLoc, "UNREFERENCED_PARAMETER"))
+ return;
+ }
+
// Okay, we have an unused result. Depending on what the base expression is,
// we might want to make a more specific diagnostic. Check for one of these
// cases now.
@@ -483,13 +492,6 @@ StmtResult
Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
Stmt *thenStmt, SourceLocation ElseLoc,
Stmt *elseStmt) {
- // If the condition was invalid, discard the if statement. We could recover
- // better by replacing it with a valid expr, but don't do that yet.
- if (!CondVal.get() && !CondVar) {
- getCurFunction()->setHasDroppedStmt();
- return StmtError();
- }
-
ExprResult CondResult(CondVal.release());
VarDecl *ConditionVar = nullptr;
@@ -497,22 +499,23 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc);
- if (CondResult.isInvalid())
- return StmtError();
}
Expr *ConditionExpr = CondResult.getAs<Expr>();
- if (!ConditionExpr)
- return StmtError();
+ if (ConditionExpr) {
+ DiagnoseUnusedExprResult(thenStmt);
- DiagnoseUnusedExprResult(thenStmt);
+ if (!elseStmt) {
+ DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
+ diag::warn_empty_if_body);
+ }
- if (!elseStmt) {
- DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
- diag::warn_empty_if_body);
+ DiagnoseUnusedExprResult(elseStmt);
+ } else {
+ // Create a dummy Expr for the condition for error recovery
+ ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(),
+ Context.BoolTy, VK_RValue);
}
- DiagnoseUnusedExprResult(elseStmt);
-
return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
thenStmt, ElseLoc, elseStmt);
}
@@ -698,8 +701,6 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
EnumValsTy::iterator &EI,
EnumValsTy::iterator &EIEnd,
const llvm::APSInt &Val) {
- bool FlagType = ED->hasAttr<FlagEnumAttr>();
-
if (const DeclRefExpr *DRE =
dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
@@ -711,7 +712,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
}
}
- if (FlagType) {
+ if (ED->hasAttr<FlagEnumAttr>()) {
return !S.IsValueInFlagEnum(ED, Val, false);
} else {
while (EI != EIEnd && EI->first < Val)
@@ -1349,7 +1350,7 @@ namespace {
}; // end class DeclExtractor
- // DeclMatcher checks to see if the decls are used in a non-evauluated
+ // DeclMatcher checks to see if the decls are used in a non-evaluated
// context.
class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> {
llvm::SmallPtrSetImpl<VarDecl*> &Decls;
@@ -1705,11 +1706,10 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
// 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 &&
- RequireCompleteType(forLoc, QualType(objectType, 0),
- getLangOpts().ObjCAutoRefCount
- ? diag::err_arc_collection_forward
- : 0,
- collection)) {
+ (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()) {
@@ -1867,13 +1867,19 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
}
namespace {
+// An enum to represent whether something is dealing with a call to begin()
+// or a call to end() in a range-based for loop.
+enum BeginEndFunction {
+ BEF_begin,
+ BEF_end
+};
/// Produce a note indicating which begin/end function was implicitly called
/// by a C++11 for-range statement. This is often not obvious from the code,
/// nor from the diagnostics produced when analysing the implicit expressions
/// required in a for-range statement.
void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
- Sema::BeginEndFunction BEF) {
+ BeginEndFunction BEF) {
CallExpr *CE = dyn_cast<CallExpr>(E);
if (!CE)
return;
@@ -1931,10 +1937,11 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
///
/// The body of the loop is not available yet, since it cannot be analysed until
/// we have determined the type of the for-range-declaration.
-StmtResult
-Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
- Stmt *First, SourceLocation ColonLoc, Expr *Range,
- SourceLocation RParenLoc, BuildForRangeKind Kind) {
+StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
+ SourceLocation CoawaitLoc, Stmt *First,
+ SourceLocation ColonLoc, Expr *Range,
+ SourceLocation RParenLoc,
+ BuildForRangeKind Kind) {
if (!First)
return StmtError();
@@ -1956,6 +1963,13 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
return StmtError();
}
+ // Coroutines: 'for co_await' implicitly co_awaits its range.
+ if (CoawaitLoc.isValid()) {
+ ExprResult Coawait = ActOnCoawaitExpr(S, CoawaitLoc, Range);
+ if (Coawait.isInvalid()) return StmtError();
+ Range = Coawait.get();
+ }
+
// Build auto && __range = range-init
SourceLocation RangeLoc = Range->getLocStart();
VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
@@ -1977,7 +1991,7 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
return StmtError();
}
- return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(),
+ return BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc, RangeDecl.get(),
/*BeginEndDecl=*/nullptr, /*Cond=*/nullptr,
/*Inc=*/nullptr, DS, RParenLoc, Kind);
}
@@ -1991,7 +2005,7 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
/// BeginExpr and EndExpr are set and FRS_Success is returned on success;
/// CandidateSet and BEF are set and some non-success value is returned on
/// failure.
-static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
+static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef,
Expr *BeginRange, Expr *EndRange,
QualType RangeType,
VarDecl *BeginVar,
@@ -2000,7 +2014,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
OverloadCandidateSet *CandidateSet,
ExprResult *BeginExpr,
ExprResult *EndExpr,
- Sema::BeginEndFunction *BEF) {
+ BeginEndFunction *BEF) {
DeclarationNameInfo BeginNameInfo(
&SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc);
DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"),
@@ -2021,7 +2035,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
if (BeginMemberLookup.empty() != EndMemberLookup.empty()) {
SourceLocation RangeLoc = BeginVar->getLocation();
- *BEF = BeginMemberLookup.empty() ? Sema::BEF_end : Sema::BEF_begin;
+ *BEF = BeginMemberLookup.empty() ? BEF_end : BEF_begin;
SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch)
<< RangeLoc << BeginRange->getType() << *BEF;
@@ -2035,29 +2049,35 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
}
- *BEF = Sema::BEF_begin;
+ *BEF = BEF_begin;
Sema::ForRangeStatus RangeStatus =
- SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, BeginVar,
- Sema::BEF_begin, BeginNameInfo,
+ SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo,
BeginMemberLookup, CandidateSet,
BeginRange, BeginExpr);
- if (RangeStatus != Sema::FRS_Success)
+ if (RangeStatus != Sema::FRS_Success) {
+ if (RangeStatus == Sema::FRS_DiagnosticIssued)
+ SemaRef.Diag(BeginRange->getLocStart(), diag::note_in_for_range)
+ << ColonLoc << BEF_begin << BeginRange->getType();
return RangeStatus;
+ }
if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc,
diag::err_for_range_iter_deduction_failure)) {
NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);
return Sema::FRS_DiagnosticIssued;
}
- *BEF = Sema::BEF_end;
+ *BEF = BEF_end;
RangeStatus =
- SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, EndVar,
- Sema::BEF_end, EndNameInfo,
+ SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo,
EndMemberLookup, CandidateSet,
EndRange, EndExpr);
- if (RangeStatus != Sema::FRS_Success)
+ if (RangeStatus != Sema::FRS_Success) {
+ if (RangeStatus == Sema::FRS_DiagnosticIssued)
+ SemaRef.Diag(EndRange->getLocStart(), diag::note_in_for_range)
+ << ColonLoc << BEF_end << EndRange->getType();
return RangeStatus;
+ }
if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc,
diag::err_for_range_iter_deduction_failure)) {
NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF);
@@ -2071,6 +2091,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
/// and emit no diagnostics.
static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
Stmt *LoopVarDecl,
SourceLocation ColonLoc,
Expr *Range,
@@ -2086,10 +2107,9 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
if (AdjustedRange.isInvalid())
return StmtResult();
- StmtResult SR =
- SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc,
- AdjustedRange.get(), RParenLoc,
- Sema::BFRK_Check);
+ StmtResult SR = SemaRef.ActOnCXXForRangeStmt(
+ S, ForLoc, CoawaitLoc, LoopVarDecl, ColonLoc, AdjustedRange.get(),
+ RParenLoc, Sema::BFRK_Check);
if (SR.isInvalid())
return StmtResult();
}
@@ -2099,8 +2119,8 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
// case there are any other (non-fatal) problems with it.
SemaRef.Diag(RangeLoc, diag::err_for_range_dereference)
<< Range->getType() << FixItHint::CreateInsertion(RangeLoc, "*");
- return SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc,
- AdjustedRange.get(), RParenLoc,
+ return SemaRef.ActOnCXXForRangeStmt(S, ForLoc, CoawaitLoc, LoopVarDecl,
+ ColonLoc, AdjustedRange.get(), RParenLoc,
Sema::BFRK_Rebuild);
}
@@ -2122,10 +2142,20 @@ struct InvalidateOnErrorScope {
/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement.
StmtResult
-Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
+Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
+ SourceLocation ColonLoc,
Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond,
Expr *Inc, Stmt *LoopVarDecl,
SourceLocation RParenLoc, BuildForRangeKind Kind) {
+ // FIXME: This should not be used during template instantiation. We should
+ // pick up the set of unqualified lookup results for the != and + operators
+ // in the initial parse.
+ //
+ // Testcase (accepts-invalid):
+ // template<typename T> void f() { for (auto x : T()) {} }
+ // namespace N { struct X { X begin(); X end(); int operator*(); }; }
+ // bool operator!=(N::X, N::X); void operator++(N::X);
+ // void g() { f<N::X>(); }
Scope *S = getCurScope();
DeclStmt *RangeDS = cast<DeclStmt>(RangeDecl);
@@ -2225,9 +2255,9 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
} else {
OverloadCandidateSet CandidateSet(RangeLoc,
OverloadCandidateSet::CSK_Normal);
- Sema::BeginEndFunction BEFFailure;
+ BeginEndFunction BEFFailure;
ForRangeStatus RangeStatus =
- BuildNonArrayForRange(*this, S, BeginRangeRef.get(),
+ BuildNonArrayForRange(*this, BeginRangeRef.get(),
EndRangeRef.get(), RangeType,
BeginVar, EndVar, ColonLoc, &CandidateSet,
&BeginExpr, &EndExpr, &BEFFailure);
@@ -2252,6 +2282,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
// If building the range failed, try dereferencing the range expression
// unless a diagnostic was issued or the end function is problematic.
StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc,
+ CoawaitLoc,
LoopVarDecl, ColonLoc,
Range, RangeLoc,
RParenLoc);
@@ -2322,7 +2353,10 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
return StmtError();
IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get());
- IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
+ if (!IncrExpr.isInvalid() && CoawaitLoc.isValid())
+ IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
+ if (!IncrExpr.isInvalid())
+ IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
if (IncrExpr.isInvalid()) {
Diag(RangeLoc, diag::note_for_range_invalid_iterator)
<< RangeLoc << 2 << BeginRangeRef.get()->getType() ;
@@ -2361,7 +2395,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
return new (Context) CXXForRangeStmt(
RangeDS, cast_or_null<DeclStmt>(BeginEndDecl.get()), NotEqExpr.get(),
- IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, ColonLoc, RParenLoc);
+ IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, CoawaitLoc,
+ ColonLoc, RParenLoc);
}
/// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach
@@ -2919,6 +2954,9 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (CurCap->HasImplicitReturnType || NRVOCandidate)
FunctionScopes.back()->Returns.push_back(Result);
+ if (FunctionScopes.back()->FirstReturnLoc.isInvalid())
+ FunctionScopes.back()->FirstReturnLoc = ReturnLoc;
+
return Result;
}
@@ -2989,14 +3027,9 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
// statement with a non-type-dependent operand.
assert(AT->isDeduced() && "should have deduced to dependent type");
return false;
- } else if (RetExpr) {
- // If the deduction is for a return statement and the initializer is
- // a braced-init-list, the program is ill-formed.
- if (isa<InitListExpr>(RetExpr)) {
- Diag(RetExpr->getExprLoc(), diag::err_auto_fn_return_init_list);
- return true;
- }
+ }
+ if (RetExpr) {
// Otherwise, [...] deduce a value for U using the rules of template
// argument deduction.
DeduceAutoResult DAR = DeduceAutoType(OrigResultType, RetExpr, Deduced);
@@ -3035,8 +3068,11 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
// the program is ill-formed.
if (AT->isDeduced() && !FD->isInvalidDecl()) {
AutoType *NewAT = Deduced->getContainedAutoType();
- if (!FD->isDependentContext() &&
- !Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) {
+ CanQualType OldDeducedType = Context.getCanonicalFunctionResultType(
+ AT->getDeducedType());
+ CanQualType NewDeducedType = Context.getCanonicalFunctionResultType(
+ NewAT->getDeducedType());
+ if (!FD->isDependentContext() && OldDeducedType != NewDeducedType) {
const LambdaScopeInfo *LambdaSI = getCurLambda();
if (LambdaSI && LambdaSI->HasImplicitReturnType) {
Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible)
@@ -3179,7 +3215,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
// return (some void expression); is legal in C++.
else if (D != diag::ext_return_has_void_expr ||
- !getLangOpts().CPlusPlus) {
+ !getLangOpts().CPlusPlus) {
NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
int FunctionKind = 0;
@@ -3287,6 +3323,9 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (Result->getNRVOCandidate())
FunctionScopes.back()->Returns.push_back(Result);
+ if (FunctionScopes.back()->FirstReturnLoc.isInvalid())
+ FunctionScopes.back()->FirstReturnLoc = ReturnLoc;
+
return Result;
}
@@ -3512,16 +3551,14 @@ public:
CXXCatchStmt *getFoundHandler() const { return FoundHandler; }
CanQualType getFoundHandlerType() const { return FoundHandlerType; }
- static bool FindPublicBasesOfType(const CXXBaseSpecifier *S, CXXBasePath &,
- void *User) {
- auto &PBOT = *reinterpret_cast<CatchTypePublicBases *>(User);
+ bool operator()(const CXXBaseSpecifier *S, CXXBasePath &) {
if (S->getAccessSpecifier() == AccessSpecifier::AS_public) {
- CatchHandlerType Check(S->getType(), PBOT.CheckAgainstPointer);
- auto M = PBOT.TypesToCheck;
+ CatchHandlerType Check(S->getType(), CheckAgainstPointer);
+ auto M = TypesToCheck;
auto I = M.find(Check);
if (I != M.end()) {
- PBOT.FoundHandler = I->second;
- PBOT.FoundHandlerType = PBOT.Ctx.getCanonicalType(S->getType());
+ FoundHandler = I->second;
+ FoundHandlerType = Ctx.getCanonicalType(S->getType());
return true;
}
}
@@ -3589,8 +3626,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
CXXBasePaths Paths;
Paths.setOrigin(RD);
CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer());
- if (RD->lookupInBases(CatchTypePublicBases::FindPublicBasesOfType, &CTPB,
- Paths)) {
+ if (RD->lookupInBases(CTPB, Paths)) {
const CXXCatchStmt *Problem = CTPB.getFoundHandler();
if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) {
Diag(H->getExceptionDecl()->getTypeSpecStartLoc(),
@@ -3766,11 +3802,10 @@ static void buildCapturedStmtCaptureList(
continue;
}
- assert(Cap->isReferenceCapture() &&
- "non-reference capture not yet implemented");
-
Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
- CapturedStmt::VCK_ByRef,
+ Cap->isReferenceCapture()
+ ? CapturedStmt::VCK_ByRef
+ : CapturedStmt::VCK_ByCopy,
Cap->getVariable()));
CaptureInits.push_back(Cap->getInitExpr());
}
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 8e3e89f1e572..0d6e0f8e41b0 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -107,6 +107,37 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) {
return false;
}
+/// \brief Returns true if given expression is not compatible with inline
+/// assembly's memory constraint; false otherwise.
+static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
+ TargetInfo::ConstraintInfo &Info,
+ bool is_input_expr) {
+ enum {
+ ExprBitfield = 0,
+ ExprVectorElt,
+ ExprGlobalRegVar,
+ ExprSafeType
+ } EType = ExprSafeType;
+
+ // Bitfields, vector elements and global register variables are not
+ // compatible.
+ if (E->refersToBitField())
+ EType = ExprBitfield;
+ else if (E->refersToVectorElement())
+ EType = ExprVectorElt;
+ else if (E->refersToGlobalRegisterVar())
+ EType = ExprGlobalRegVar;
+
+ if (EType != ExprSafeType) {
+ S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
+ << EType << is_input_expr << Info.getConstraintStr()
+ << E->getSourceRange();
+ return true;
+ }
+
+ return false;
+}
+
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
bool IsVolatile, unsigned NumOutputs,
unsigned NumInputs, IdentifierInfo **Names,
@@ -124,8 +155,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
// The parser verifies that there is a string literal here.
assert(AsmString->isAscii());
- bool ValidateConstraints =
- DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl());
+ // If we're compiling CUDA file and function attributes indicate that it's not
+ // for this compilation side, skip all the checks.
+ if (!DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) {
+ GCCAsmStmt *NS = new (Context) GCCAsmStmt(
+ Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
+ Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
+ return NS;
+ }
for (unsigned i = 0; i != NumOutputs; i++) {
StringLiteral *Literal = Constraints[i];
@@ -136,8 +173,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
OutputName = Names[i]->getName();
TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
- if (ValidateConstraints &&
- !Context.getTargetInfo().validateOutputConstraint(Info))
+ if (!Context.getTargetInfo().validateOutputConstraint(Info))
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_invalid_output_constraint)
<< Info.getConstraintStr());
@@ -154,13 +190,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (CheckNakedParmReference(OutputExpr, *this))
return StmtError();
- // Bitfield can't be referenced with a pointer.
- if (Info.allowsMemory() && OutputExpr->refersToBitField())
- return StmtError(Diag(OutputExpr->getLocStart(),
- diag::err_asm_bitfield_in_memory_constraint)
- << 1
- << Info.getConstraintStr()
- << OutputExpr->getSourceRange());
+ // Check that the output expression is compatible with memory constraint.
+ if (Info.allowsMemory() &&
+ checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
+ return StmtError();
OutputConstraintInfos.push_back(Info);
@@ -219,9 +252,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
InputName = Names[i]->getName();
TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
- if (ValidateConstraints &&
- !Context.getTargetInfo().validateInputConstraint(
- OutputConstraintInfos.data(), NumOutputs, Info)) {
+ if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
+ Info)) {
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_invalid_input_constraint)
<< Info.getConstraintStr());
@@ -238,13 +270,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (CheckNakedParmReference(InputExpr, *this))
return StmtError();
- // Bitfield can't be referenced with a pointer.
- if (Info.allowsMemory() && InputExpr->refersToBitField())
- return StmtError(Diag(InputExpr->getLocStart(),
- diag::err_asm_bitfield_in_memory_constraint)
- << 0
- << Info.getConstraintStr()
- << InputExpr->getSourceRange());
+ // Check that the input expression is compatible with memory constraint.
+ if (Info.allowsMemory() &&
+ checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
+ return StmtError();
// Only allow void types for memory constraints.
if (Info.allowsMemory() && !Info.allowsRegister()) {
@@ -260,8 +289,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return StmtError(
Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
<< Info.getConstraintStr() << InputExpr->getSourceRange());
- if (Result.slt(Info.getImmConstantMin()) ||
- Result.sgt(Info.getImmConstantMax()))
+ if (!Info.isValidAsmImmediate(Result))
return StmtError(Diag(InputExpr->getLocStart(),
diag::err_invalid_asm_value_for_constraint)
<< Result.toString(10) << Info.getConstraintStr()
@@ -392,6 +420,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
diag::err_asm_unexpected_constraint_alternatives)
<< NumAlternatives << AltCount);
}
+ SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(),
+ ~0U);
for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
StringRef ConstraintStr = Info.getConstraintStr();
@@ -413,6 +443,19 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
Expr *OutputExpr = Exprs[TiedTo];
Expr *InputExpr = Exprs[InputOpNo];
+ // Make sure no more than one input constraint matches each output.
+ assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range");
+ if (InputMatchedToOutput[TiedTo] != ~0U) {
+ Diag(NS->getInputExpr(i)->getLocStart(),
+ diag::err_asm_input_duplicate_match)
+ << TiedTo;
+ Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(),
+ diag::note_asm_input_duplicate_first)
+ << TiedTo;
+ return StmtError();
+ }
+ InputMatchedToOutput[TiedTo] = i;
+
if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
continue;
@@ -504,6 +547,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return NS;
}
+static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T,
+ llvm::InlineAsmIdentifierInfo &Info) {
+ // Compute the type size (and array length if applicable?).
+ Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
+ if (T->isArrayType()) {
+ const ArrayType *ATy = Context.getAsArrayType(T);
+ Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
+ Info.Length = Info.Size / Info.Type;
+ }
+}
+
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
@@ -551,13 +605,7 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
return ExprError();
}
- // Compute the type size (and array length if applicable?).
- Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
- if (T->isArrayType()) {
- const ArrayType *ATy = Context.getAsArrayType(T);
- Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
- Info.Length = Info.Size / Info.Type;
- }
+ fillInlineAsmTypeInfo(Context, T, Info);
// We can work with the expression as long as it's not an r-value.
if (!Result.get()->isRValue())
@@ -569,47 +617,103 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset, SourceLocation AsmLoc) {
Offset = 0;
+ SmallVector<StringRef, 2> Members;
+ Member.split(Members, ".");
+
LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
LookupOrdinaryName);
if (!LookupName(BaseResult, getCurScope()))
return true;
- if (!BaseResult.isSingleResult())
- return true;
+ LookupResult CurrBaseResult(BaseResult);
- const RecordType *RT = nullptr;
- NamedDecl *FoundDecl = BaseResult.getFoundDecl();
- if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
- RT = VD->getType()->getAs<RecordType>();
- else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
- MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
- RT = TD->getUnderlyingType()->getAs<RecordType>();
- } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
- RT = TD->getTypeForDecl()->getAs<RecordType>();
- if (!RT)
- return true;
+ for (StringRef NextMember : Members) {
- if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0))
- return true;
+ if (!CurrBaseResult.isSingleResult())
+ return true;
+
+ const RecordType *RT = nullptr;
+ NamedDecl *FoundDecl = CurrBaseResult.getFoundDecl();
+ if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
+ RT = VD->getType()->getAs<RecordType>();
+ else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
+ MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
+ RT = TD->getUnderlyingType()->getAs<RecordType>();
+ } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
+ RT = TD->getTypeForDecl()->getAs<RecordType>();
+ else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
+ RT = TD->getType()->getAs<RecordType>();
+ if (!RT)
+ return true;
+
+ if (RequireCompleteType(AsmLoc, QualType(RT, 0),
+ diag::err_asm_incomplete_type))
+ return true;
+
+ LookupResult FieldResult(*this, &Context.Idents.get(NextMember),
+ SourceLocation(), LookupMemberName);
+
+ if (!LookupQualifiedName(FieldResult, RT->getDecl()))
+ return true;
+
+ // FIXME: Handle IndirectFieldDecl?
+ FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
+ if (!FD)
+ return true;
+
+ CurrBaseResult = FieldResult;
+
+ const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
+ unsigned i = FD->getFieldIndex();
+ CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
+ Offset += (unsigned)Result.getQuantity();
+ }
+
+ return false;
+}
- LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(),
+ExprResult
+Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, unsigned &Offset,
+ llvm::InlineAsmIdentifierInfo &Info,
+ SourceLocation AsmLoc) {
+ Info.clear();
+
+ const RecordType *RT = E->getType()->getAs<RecordType>();
+ // FIXME: Diagnose this as field access into a scalar type.
+ if (!RT)
+ return ExprResult();
+
+ LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc,
LookupMemberName);
if (!LookupQualifiedName(FieldResult, RT->getDecl()))
- return true;
+ return ExprResult();
- // FIXME: Handle IndirectFieldDecl?
- FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
+ // Only normal and indirect field results will work.
+ ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
if (!FD)
- return true;
+ FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl());
+ if (!FD)
+ return ExprResult();
- const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
- unsigned i = FD->getFieldIndex();
- CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
- Offset = (unsigned)Result.getQuantity();
+ Offset = (unsigned)Context.toCharUnitsFromBits(Context.getFieldOffset(FD))
+ .getQuantity();
- return false;
+ // Make an Expr to thread through OpDecl.
+ ExprResult Result = BuildMemberReferenceExpr(
+ E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
+ SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
+ if (Result.isInvalid())
+ return Result;
+ Info.OpDecl = Result.get();
+
+ fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info);
+
+ // Fields are "variables" as far as inline assembly is concerned.
+ Info.IsVarDecl = true;
+
+ return Result;
}
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
@@ -646,7 +750,15 @@ LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
// Create an internal name for the label. The name should not be a valid mangled
// name, and should be unique. We use a dot to make the name an invalid mangled
// name.
- OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__" << ExternalLabelName;
+ OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__";
+ for (auto it = ExternalLabelName.begin(); it != ExternalLabelName.end();
+ ++it) {
+ OS << *it;
+ if (*it == '$') {
+ // We escape '$' in asm strings by replacing it with "$$"
+ OS << '$';
+ }
+ }
Label->setMSAsmLabel(OS.str());
}
if (AlwaysCreate) {
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 5b71c11b5297..984bd078fa03 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -65,19 +65,32 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
return nullptr;
}
- LoopHintAttr::OptionType Option;
LoopHintAttr::Spelling Spelling;
- if (PragmaUnroll) {
- Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
- Spelling = LoopHintAttr::Pragma_unroll;
- } else if (PragmaNoUnroll) {
- Option = LoopHintAttr::Unroll;
+ LoopHintAttr::OptionType Option;
+ LoopHintAttr::LoopHintState State;
+ if (PragmaNoUnroll) {
+ // #pragma nounroll
Spelling = LoopHintAttr::Pragma_nounroll;
+ Option = LoopHintAttr::Unroll;
+ State = LoopHintAttr::Disable;
+ } else if (PragmaUnroll) {
+ Spelling = LoopHintAttr::Pragma_unroll;
+ if (ValueExpr) {
+ // #pragma unroll N
+ Option = LoopHintAttr::UnrollCount;
+ State = LoopHintAttr::Numeric;
+ } else {
+ // #pragma unroll
+ Option = LoopHintAttr::Unroll;
+ State = LoopHintAttr::Enable;
+ }
} else {
+ // #pragma clang loop ...
+ Spelling = LoopHintAttr::Pragma_clang_loop;
assert(OptionLoc && OptionLoc->Ident &&
"Attribute must have valid option info.");
- IdentifierInfo *OptionInfo = OptionLoc->Ident;
- Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
+ Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
+ OptionLoc->Ident->getName())
.Case("vectorize", LoopHintAttr::Vectorize)
.Case("vectorize_width", LoopHintAttr::VectorizeWidth)
.Case("interleave", LoopHintAttr::Interleave)
@@ -85,31 +98,29 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
.Case("unroll", LoopHintAttr::Unroll)
.Case("unroll_count", LoopHintAttr::UnrollCount)
.Default(LoopHintAttr::Vectorize);
- Spelling = LoopHintAttr::Pragma_clang_loop;
- }
-
- LoopHintAttr::LoopHintState State = LoopHintAttr::Default;
- if (PragmaNoUnroll) {
- State = LoopHintAttr::Disable;
- } else if (Option == LoopHintAttr::VectorizeWidth ||
- Option == LoopHintAttr::InterleaveCount ||
- Option == LoopHintAttr::UnrollCount) {
- assert(ValueExpr && "Attribute must have a valid value expression.");
- if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
- return nullptr;
- } else if (Option == LoopHintAttr::Vectorize ||
- Option == LoopHintAttr::Interleave ||
- Option == LoopHintAttr::Unroll) {
- // Default state is assumed if StateLoc is not specified, such as with
- // '#pragma unroll'.
- if (StateLoc && StateLoc->Ident) {
+ if (Option == LoopHintAttr::VectorizeWidth ||
+ Option == LoopHintAttr::InterleaveCount ||
+ Option == LoopHintAttr::UnrollCount) {
+ assert(ValueExpr && "Attribute must have a valid value expression.");
+ if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
+ return nullptr;
+ State = LoopHintAttr::Numeric;
+ } else if (Option == LoopHintAttr::Vectorize ||
+ Option == LoopHintAttr::Interleave ||
+ Option == LoopHintAttr::Unroll) {
+ assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
if (StateLoc->Ident->isStr("disable"))
State = LoopHintAttr::Disable;
else if (StateLoc->Ident->isStr("assume_safety"))
State = LoopHintAttr::AssumeSafety;
- else
+ else if (StateLoc->Ident->isStr("full"))
+ State = LoopHintAttr::Full;
+ else if (StateLoc->Ident->isStr("enable"))
State = LoopHintAttr::Enable;
- }
+ else
+ llvm_unreachable("bad loop hint argument");
+ } else
+ llvm_unreachable("bad loop hint");
}
return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State,
@@ -139,9 +150,8 @@ CheckForIncompatibleAttributes(Sema &S,
if (!LH)
continue;
- int Option = LH->getOption();
- int Category;
- enum { Vectorize, Interleave, Unroll };
+ LoopHintAttr::OptionType Option = LH->getOption();
+ enum { Vectorize, Interleave, Unroll } Category;
switch (Option) {
case LoopHintAttr::Vectorize:
case LoopHintAttr::VectorizeWidth:
@@ -183,7 +193,8 @@ CheckForIncompatibleAttributes(Sema &S,
CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
// Disable hints are not compatible with numeric hints of the same
// category. As a special case, numeric unroll hints are also not
- // compatible with "enable" form of the unroll pragma, unroll(full).
+ // compatible with enable or full form of the unroll pragma because these
+ // directives indicate full unrolling.
S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
<< /*Duplicate=*/false
<< CategoryState.StateAttr->getDiagnosticName(Policy)
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 035c37cfe6e9..6cc85883345d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
@@ -208,7 +209,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
R.suppressDiagnostics();
} else {
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
- isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD));
+ isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) ||
+ isa<BuiltinTemplateDecl>(TD));
TemplateKind =
isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
}
@@ -327,8 +329,8 @@ void Sema::LookupTemplateName(LookupResult &Found,
Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS,
std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) {
Found.setLookupName(Corrected.getCorrection());
- if (Corrected.getCorrectionDecl())
- Found.addDecl(Corrected.getCorrectionDecl());
+ if (auto *ND = Corrected.getFoundDecl())
+ Found.addDecl(ND);
FilterAcceptableTemplateNames(Found);
if (!Found.empty()) {
if (LookupCtx) {
@@ -812,14 +814,15 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- Decl **Params, unsigned NumParams,
+ ArrayRef<Decl *> Params,
SourceLocation RAngleLoc) {
if (ExportLoc.isValid())
Diag(ExportLoc, diag::warn_template_export_unsupported);
- return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
- (NamedDecl**)Params, NumParams,
- RAngleLoc);
+ return TemplateParameterList::Create(
+ Context, TemplateLoc, LAngleLoc,
+ llvm::makeArrayRef((NamedDecl *const *)Params.data(), Params.size()),
+ RAngleLoc);
}
static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
@@ -1089,9 +1092,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(NewClass, SS);
if (NumOuterTemplateParamLists > 0)
- NewClass->setTemplateParameterListsInfo(Context,
- NumOuterTemplateParamLists,
- OuterTemplateParamLists);
+ NewClass->setTemplateParameterListsInfo(
+ Context, llvm::makeArrayRef(OuterTemplateParamLists,
+ NumOuterTemplateParamLists));
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
@@ -1936,7 +1939,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// Fabricate an empty template parameter list for the invented header.
return TemplateParameterList::Create(Context, SourceLocation(),
- SourceLocation(), nullptr, 0,
+ SourceLocation(), None,
SourceLocation());
}
@@ -2017,6 +2020,58 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
}
}
+static QualType
+checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
+ const SmallVectorImpl<TemplateArgument> &Converted,
+ SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs) {
+ ASTContext &Context = SemaRef.getASTContext();
+ switch (BTD->getBuiltinTemplateKind()) {
+ case BTK__make_integer_seq:
+ // Specializations of __make_integer_seq<S, T, N> are treated like
+ // S<T, 0, ..., N-1>.
+
+ // C++14 [inteseq.intseq]p1:
+ // T shall be an integer type.
+ if (!Converted[1].getAsType()->isIntegralType(Context)) {
+ SemaRef.Diag(TemplateArgs[1].getLocation(),
+ diag::err_integer_sequence_integral_element_type);
+ return QualType();
+ }
+
+ // C++14 [inteseq.make]p1:
+ // If N is negative the program is ill-formed.
+ TemplateArgument NumArgsArg = Converted[2];
+ llvm::APSInt NumArgs = NumArgsArg.getAsIntegral();
+ if (NumArgs < 0) {
+ SemaRef.Diag(TemplateArgs[2].getLocation(),
+ diag::err_integer_sequence_negative_length);
+ return QualType();
+ }
+
+ QualType ArgTy = NumArgsArg.getIntegralType();
+ TemplateArgumentListInfo SyntheticTemplateArgs;
+ // The type argument gets reused as the first template argument in the
+ // synthetic template argument list.
+ SyntheticTemplateArgs.addArgument(TemplateArgs[1]);
+ // Expand N into 0 ... N-1.
+ for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
+ I < NumArgs; ++I) {
+ TemplateArgument TA(Context, I, ArgTy);
+ Expr *E = SemaRef.BuildExpressionFromIntegralTemplateArgument(
+ TA, TemplateArgs[2].getLocation())
+ .getAs<Expr>();
+ SyntheticTemplateArgs.addArgument(
+ TemplateArgumentLoc(TemplateArgument(E), E));
+ }
+ // The first template argument will be reused as the template decl that
+ // our synthetic template arguments will be applied to.
+ return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(),
+ TemplateLoc, SyntheticTemplateArgs);
+ }
+ llvm_unreachable("unexpected BuiltinTemplateDecl!");
+}
+
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
@@ -2171,6 +2226,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
CanonType = Context.getTypeDeclType(Decl);
assert(isa<RecordType>(CanonType) &&
"type of non-dependent specialization is not a RecordType");
+ } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
+ CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc,
+ TemplateArgs);
}
// Build the fully-sugared type for this class template
@@ -2469,25 +2527,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
false, Converted))
return true;
- // Check that the type of this variable template specialization
- // matches the expected type.
- TypeSourceInfo *ExpectedDI;
- {
- // Do substitution on the type of the declaration
- TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
- Converted.data(), Converted.size());
- InstantiatingTemplate Inst(*this, TemplateKWLoc, VarTemplate);
- if (Inst.isInvalid())
- return true;
- VarDecl *Templated = VarTemplate->getTemplatedDecl();
- ExpectedDI =
- SubstType(Templated->getTypeSourceInfo(),
- MultiLevelTemplateArgumentList(TemplateArgList),
- Templated->getTypeSpecStartLoc(), Templated->getDeclName());
- }
- if (!ExpectedDI)
- return true;
-
// Find the variable template (partial) specialization declaration that
// corresponds to these arguments.
if (IsPartialSpecialization) {
@@ -2710,7 +2749,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
typedef PartialSpecMatchResult MatchResult;
SmallVector<MatchResult, 4> Matched;
SourceLocation PointOfInstantiation = TemplateNameLoc;
- TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
+ TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation,
+ /*ForTakingAddress=*/false);
// 1. Attempt to find the closest partial specialization that this
// specializes, if any.
@@ -3242,7 +3282,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateArgLists.addOuterTemplateArguments(None);
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+ EnterExpressionEvaluationContext ConstantEvaluated(SemaRef,
+ Sema::ConstantEvaluated);
return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists);
}
@@ -3733,9 +3774,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// We're done with this parameter pack. Pack up its arguments and add
// them to the list.
Converted.push_back(
- TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
+ TemplateArgument::CreatePackCopy(Context, ArgumentPack));
ArgumentPack.clear();
// This argument is assigned to the next parameter.
@@ -3816,10 +3855,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// If we're checking a partial template argument list, we're done.
if (PartialTemplateArgs) {
if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty())
- Converted.push_back(TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
-
+ Converted.push_back(
+ TemplateArgument::CreatePackCopy(Context, ArgumentPack));
+
return false;
}
@@ -3835,9 +3873,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (Param + 1 != ParamEnd)
return true;
- Converted.push_back(TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
+ Converted.push_back(
+ TemplateArgument::CreatePackCopy(Context, ArgumentPack));
ArgumentPack.clear();
++Param;
@@ -3946,7 +3983,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// No problems found with the new argument list, propagate changes back
// to caller.
- TemplateArgs = NewArgs;
+ TemplateArgs = std::move(NewArgs);
return false;
}
@@ -4245,7 +4282,11 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
QualType ParamType, Expr *Arg) {
if (Arg->isValueDependent() || Arg->isTypeDependent())
return NPV_NotNullPointer;
-
+
+ if (!S.isCompleteType(Arg->getExprLoc(), ParamType))
+ llvm_unreachable(
+ "Incomplete parameter type in isNullPointerValueTemplateArgument!");
+
if (!S.getLangOpts().CPlusPlus11)
return NPV_NotNullPointer;
@@ -4693,8 +4734,6 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument(S.Context.getCanonicalType(ParamType),
/*isNullPtr*/true);
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft())
- S.RequireCompleteType(Arg->getExprLoc(), ParamType, 0);
return false;
case NPV_NotNullPointer:
break;
@@ -6311,9 +6350,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
PrevPartial);
SetNestedNameSpecifier(Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
- Partial->setTemplateParameterListsInfo(Context,
- TemplateParameterLists.size() - 1,
- TemplateParameterLists.data());
+ Partial->setTemplateParameterListsInfo(
+ Context, TemplateParameterLists.drop_back(1));
}
if (!PrevPartial)
@@ -6367,14 +6405,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
SetNestedNameSpecifier(Specialization, SS);
if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
- TemplateParameterLists.size(),
- TemplateParameterLists.data());
+ TemplateParameterLists);
}
if (!PrevDecl)
ClassTemplate->AddSpecialization(Specialization, InsertPos);
- CanonType = Context.getTypeDeclType(Specialization);
+ if (CurContext->isDependentContext()) {
+ // -fms-extensions permits specialization of nested classes without
+ // fully specializing the outer class(es).
+ assert(getLangOpts().MicrosoftExt &&
+ "Only possible with -fms-extensions!");
+ TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+ CanonType = Context.getTemplateSpecializationType(
+ CanonTemplate, Converted.data(), Converted.size());
+ } else {
+ CanonType = Context.getTypeDeclType(Specialization);
+ }
}
// C++ [temp.expl.spec]p6:
@@ -6497,24 +6544,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
return NewDecl;
}
-Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D) {
- assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
- DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
-
- if (FTI.hasPrototype) {
- // FIXME: Diagnose arguments without names in C.
- }
-
- Scope *ParentScope = FnBodyScope->getParent();
-
- D.setFunctionDefinitionKind(FDK_Definition);
- Decl *DP = HandleDeclarator(ParentScope, D,
- TemplateParameterLists);
- return ActOnStartOfFunctionDef(FnBodyScope, DP);
-}
-
/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
@@ -6795,7 +6824,11 @@ bool Sema::CheckFunctionTemplateSpecialization(
// The set of function template specializations that could match this
// explicit function template specialization.
UnresolvedSet<8> Candidates;
- TemplateSpecCandidateSet FailedCandidates(FD->getLocation());
+ TemplateSpecCandidateSet FailedCandidates(FD->getLocation(),
+ /*ForTakingAddress=*/false);
+
+ llvm::SmallDenseMap<FunctionDecl *, TemplateArgumentListInfo, 8>
+ ConvertedTemplateArgs;
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
@@ -6826,6 +6859,10 @@ bool Sema::CheckFunctionTemplateSpecialization(
}
}
+ TemplateArgumentListInfo Args;
+ if (ExplicitTemplateArgs)
+ Args = *ExplicitTemplateArgs;
+
// C++ [temp.expl.spec]p11:
// A trailing template-argument can be left unspecified in the
// template-id naming an explicit function template specialization
@@ -6837,7 +6874,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK = DeduceTemplateArguments(
cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()),
- ExplicitTemplateArgs, FT, Specialization, Info)) {
+ ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info)) {
// Template argument deduction failed; record why it failed, so
// that we can provide nifty diagnostics.
FailedCandidates.addCandidate()
@@ -6848,6 +6885,8 @@ bool Sema::CheckFunctionTemplateSpecialization(
}
// Record this candidate.
+ if (ExplicitTemplateArgs)
+ ConvertedTemplateArgs[Specialization] = std::move(Args);
Candidates.addDecl(Specialization, I.getAccess());
}
}
@@ -6926,10 +6965,10 @@ bool Sema::CheckFunctionTemplateSpecialization(
// Take copies of (semantic and syntactic) template argument lists.
const TemplateArgumentList* TemplArgs = new (Context)
TemplateArgumentList(Specialization->getTemplateSpecializationArgs());
- FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(),
- TemplArgs, /*InsertPos=*/nullptr,
- SpecInfo->getTemplateSpecializationKind(),
- ExplicitTemplateArgs);
+ FD->setFunctionTemplateSpecialization(
+ Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr,
+ SpecInfo->getTemplateSpecializationKind(),
+ ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr);
// The "previous declaration" for this function template specialization is
// the prior function template specialization.
@@ -7429,11 +7468,16 @@ Sema::ActOnExplicitInstantiation(Scope *S,
}
}
+ // Set the template specialization kind. Make sure it is set before
+ // instantiating the members which will trigger ASTConsumer callbacks.
+ Specialization->setTemplateSpecializationKind(TSK);
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
+ } else {
+
+ // Set the template specialization kind.
+ Specialization->setTemplateSpecializationKind(TSK);
}
- // Set the template specialization kind.
- Specialization->setTemplateSpecializationKind(TSK);
return Specialization;
}
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index ae8157e70a60..de04c8a7f042 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -679,7 +679,7 @@ public:
new (S.Context) TemplateArgument[Pack.New.size()];
std::copy(Pack.New.begin(), Pack.New.end(), ArgumentPack);
NewPack = DeducedTemplateArgument(
- TemplateArgument(ArgumentPack, Pack.New.size()),
+ TemplateArgument(llvm::makeArrayRef(ArgumentPack, Pack.New.size())),
Pack.New[0].wasDeducedFromArrayBound());
}
@@ -1440,7 +1440,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// We cannot inspect base classes as part of deduction when the type
// is incomplete, so either instantiate any templates necessary to
// complete the type, or skip over it if it cannot be completed.
- if (S.RequireCompleteType(Info.getLocation(), Arg, 0))
+ if (!S.isCompleteType(Info.getLocation(), Arg))
return Result;
// Use data recursion to crawl through the list of base classes.
@@ -1517,10 +1517,19 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (!MemPtrArg)
return Sema::TDK_NonDeducedMismatch;
+ QualType ParamPointeeType = MemPtrParam->getPointeeType();
+ if (ParamPointeeType->isFunctionType())
+ S.adjustMemberFunctionCC(ParamPointeeType, /*IsStatic=*/true,
+ /*IsCtorOrDtor=*/false, Info.getLocation());
+ QualType ArgPointeeType = MemPtrArg->getPointeeType();
+ if (ArgPointeeType->isFunctionType())
+ S.adjustMemberFunctionCC(ArgPointeeType, /*IsStatic=*/true,
+ /*IsCtorOrDtor=*/false, Info.getLocation());
+
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
- MemPtrParam->getPointeeType(),
- MemPtrArg->getPointeeType(),
+ ParamPointeeType,
+ ArgPointeeType,
Info, Deduced,
TDF & TDF_IgnoreQualifiers))
return Result;
@@ -2075,9 +2084,8 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
}
// Create the resulting argument pack.
- Output.push_back(TemplateArgument::CreatePackCopy(S.Context,
- PackedArgsBuilder.data(),
- PackedArgsBuilder.size()));
+ Output.push_back(
+ TemplateArgument::CreatePackCopy(S.Context, PackedArgsBuilder));
return false;
}
@@ -2730,7 +2738,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
return false;
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
- S.IsDerivedFrom(A, DeducedA))
+ S.IsDerivedFrom(SourceLocation(), A, DeducedA))
return false;
return true;
@@ -2850,7 +2858,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
&NumExplicitArgs)
== Param) {
- Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
+ Builder.push_back(TemplateArgument(
+ llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
// Forget the partially-substituted pack; it's substitution is now
// complete.
@@ -3028,7 +3037,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// Gather the explicit template arguments, if any.
TemplateArgumentListInfo ExplicitTemplateArgs;
if (Ovl->hasExplicitTemplateArgs())
- Ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+ Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
QualType Match;
for (UnresolvedSetIterator I = Ovl->decls_begin(),
E = Ovl->decls_end(); I != E; ++I) {
@@ -3123,8 +3132,10 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
if (ParamRefType) {
// If the argument has incomplete array type, try to complete its type.
- if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
+ if (ArgType->isIncompleteArrayType()) {
+ S.completeExprArrayBound(Arg);
ArgType = Arg->getType();
+ }
// C++0x [temp.deduct.call]p3:
// If P is an rvalue reference to a cv-unqualified template
@@ -3203,24 +3214,63 @@ DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF, Sema::TemplateDeductionResult &Result) {
- // If the argument is an initializer list then the parameter is an undeduced
- // context, unless the parameter type is (reference to cv)
- // std::initializer_list<P'>, in which case deduction is done for each element
- // of the initializer list as-if it were an argument in a function call, and
- // the result is the deduced type if it's the same for all elements.
- QualType X;
- if (!S.isStdInitializerList(AdjustedParamType, &X))
+
+ // [temp.deduct.call] p1 (post CWG-1591)
+ // If removing references and cv-qualifiers from P gives
+ // std::initializer_list<P0> or P0[N] for some P0 and N and the argument is a
+ // non-empty initializer list (8.5.4), then deduction is performed instead for
+ // each element of the initializer list, taking P0 as a function template
+ // parameter type and the initializer element as its argument, and in the
+ // P0[N] case, if N is a non-type template parameter, N is deduced from the
+ // length of the initializer list. Otherwise, an initializer list argument
+ // causes the parameter to be considered a non-deduced context
+
+ const bool IsConstSizedArray = AdjustedParamType->isConstantArrayType();
+
+ const bool IsDependentSizedArray =
+ !IsConstSizedArray && AdjustedParamType->isDependentSizedArrayType();
+
+ QualType ElTy; // The element type of the std::initializer_list or the array.
+
+ const bool IsSTDList = !IsConstSizedArray && !IsDependentSizedArray &&
+ S.isStdInitializerList(AdjustedParamType, &ElTy);
+
+ if (!IsConstSizedArray && !IsDependentSizedArray && !IsSTDList)
return false;
Result = Sema::TDK_Success;
-
- // Recurse down into the init list.
- for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
- if ((Result = DeduceTemplateArgumentByListElement(
- S, TemplateParams, X, ILE->getInit(i), Info, Deduced, TDF)))
- return true;
+ // If we are not deducing against the 'T' in a std::initializer_list<T> then
+ // deduce against the 'T' in T[N].
+ if (ElTy.isNull()) {
+ assert(!IsSTDList);
+ ElTy = S.Context.getAsArrayType(AdjustedParamType)->getElementType();
+ }
+ // Deduction only needs to be done for dependent types.
+ if (ElTy->isDependentType()) {
+ for (Expr *E : ILE->inits()) {
+ if ((Result = DeduceTemplateArgumentByListElement(S, TemplateParams, ElTy,
+ E, Info, Deduced, TDF)))
+ return true;
+ }
}
+ if (IsDependentSizedArray) {
+ const DependentSizedArrayType *ArrTy =
+ S.Context.getAsDependentSizedArrayType(AdjustedParamType);
+ // Determine the array bound is something we can deduce.
+ if (NonTypeTemplateParmDecl *NTTP =
+ getDeducedParameterFromExpr(ArrTy->getSizeExpr())) {
+ // We can perform template argument deduction for the given non-type
+ // template parameter.
+ assert(NTTP->getDepth() == 0 &&
+ "Cannot deduce non-type template argument at depth > 0");
+ llvm::APInt Size(S.Context.getIntWidth(NTTP->getType()),
+ ILE->getNumInits());
+ Result = DeduceNonTypeTemplateArgument(
+ S, NTTP, llvm::APSInt(Size), NTTP->getType(),
+ /*ArrayBound=*/true, Info, Deduced);
+ }
+ }
return true;
}
@@ -3908,7 +3958,7 @@ namespace {
!Replacement.isNull() && Replacement->isDependentType();
QualType Result =
SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,
- TL.getTypePtr()->isDecltypeAuto(),
+ TL.getTypePtr()->getKeyword(),
Dependent);
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
@@ -3976,6 +4026,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
if (Result.isNull())
return DAR_FailedAlreadyDiagnosed;
return DAR_Succeeded;
+ } else if (!getLangOpts().CPlusPlus) {
+ if (isa<InitListExpr>(Init)) {
+ Diag(Init->getLocStart(), diag::err_auto_init_list_from_c);
+ return DAR_FailedAlreadyDiagnosed;
+ }
}
}
@@ -3989,8 +4044,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
nullptr, false, false);
QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
NamedDecl *TemplParamPtr = TemplParam;
- FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
- Loc);
+ FixedSizeTemplateParameterListStorage<1> TemplateParamsSt(
+ Loc, Loc, TemplParamPtr, Loc);
QualType FuncParam = SubstituteAutoTransform(*this, TemplArg).Apply(Type);
assert(!FuncParam.isNull() &&
@@ -4007,20 +4062,24 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
if (InitList) {
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
- if (DeduceTemplateArgumentByListElement(*this, &TemplateParams,
- TemplArg,
- InitList->getInit(i),
+ if (DeduceTemplateArgumentByListElement(*this, TemplateParamsSt.get(),
+ TemplArg, InitList->getInit(i),
Info, Deduced, TDF))
return DAR_Failed;
}
} else {
- if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
- FuncParam, InitType, Init,
- TDF))
+ if (!getLangOpts().CPlusPlus && Init->refersToBitField()) {
+ Diag(Loc, diag::err_auto_bitfield);
+ return DAR_FailedAlreadyDiagnosed;
+ }
+
+ if (AdjustFunctionParmAndArgTypesForDeduction(
+ *this, TemplateParamsSt.get(), FuncParam, InitType, Init, TDF))
return DAR_Failed;
- if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
- InitType, Info, Deduced, TDF))
+ if (DeduceTemplateArgumentsByTypeMatch(*this, TemplateParamsSt.get(),
+ FuncParam, InitType, Info, Deduced,
+ TDF))
return DAR_Failed;
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index c1961e516ddf..fb7fc109d2e9 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -817,14 +817,6 @@ namespace {
QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
SubstTemplateTypeParmPackTypeLoc TL);
- ExprResult TransformCallExpr(CallExpr *CE) {
- getSema().CallsUndergoingInstantiation.push_back(CE);
- ExprResult Result =
- TreeTransform<TemplateInstantiator>::TransformCallExpr(CE);
- getSema().CallsUndergoingInstantiation.pop_back();
- return Result;
- }
-
ExprResult TransformLambdaExpr(LambdaExpr *E) {
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
return TreeTransform<TemplateInstantiator>::TransformLambdaExpr(E);
@@ -1231,7 +1223,7 @@ TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
// Transform each of the parameter expansions into the corresponding
// parameters in the instantiation of the function decl.
- SmallVector<Decl *, 8> Parms;
+ SmallVector<ParmVarDecl *, 8> Parms;
Parms.reserve(E->getNumExpansions());
for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
I != End; ++I) {
@@ -1682,15 +1674,17 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
} else if (Expr *Arg = OldParm->getDefaultArg()) {
FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
- CXXRecordDecl *ClassD = dyn_cast<CXXRecordDecl>(OwningFunc->getDeclContext());
- if (ClassD && ClassD->isLocalClass() && !ClassD->isLambda()) {
- // If this is a method of a local class, as per DR1484 its default
- // arguments must be instantiated.
- Sema::ContextRAII SavedContext(*this, ClassD);
+ if (OwningFunc->isLexicallyWithinFunctionOrMethod()) {
+ // Instantiate default arguments for methods of local classes (DR1484)
+ // and non-defining declarations.
+ Sema::ContextRAII SavedContext(*this, OwningFunc);
LocalInstantiationScope Local(*this);
ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
- if (NewArg.isUsable())
- NewParm->setDefaultArg(NewArg.get());
+ if (NewArg.isUsable()) {
+ // It would be nice if we still had this.
+ SourceLocation EqualLoc = NewArg.get()->getLocStart();
+ SetParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
+ }
} else {
// FIXME: if we non-lazily instantiated non-dependent default args for
// non-dependent parameter types we could remove a bunch of duplicate
@@ -1843,9 +1837,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Invalid = true;
}
- if (!Invalid &&
- AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(),
- InstantiatedBases.size()))
+ if (!Invalid && AttachBaseSpecifiers(Instantiation, InstantiatedBases))
Invalid = true;
return Invalid;
@@ -2050,7 +2042,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Default arguments are parsed, if not instantiated. We can go instantiate
// default arg exprs for default constructors if necessary now.
- ActOnFinishCXXMemberDefaultArgs(Instantiation);
+ ActOnFinishCXXNonNestedClass(Instantiation);
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
@@ -2672,16 +2664,17 @@ ExprResult Sema::SubstInitializer(Expr *Init,
return Instantiator.TransformInitializer(Init, CXXDirectInit);
}
-bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+bool Sema::SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall,
const MultiLevelTemplateArgumentList &TemplateArgs,
SmallVectorImpl<Expr *> &Outputs) {
- if (NumExprs == 0)
+ if (Exprs.empty())
return false;
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
DeclarationName());
- return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs);
+ return Instantiator.TransformExprs(Exprs.data(), Exprs.size(),
+ IsCall, Outputs);
}
NestedNameSpecifierLoc
@@ -2806,14 +2799,14 @@ void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
#endif
Stored = Inst;
} else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) {
- Pack->push_back(Inst);
+ Pack->push_back(cast<ParmVarDecl>(Inst));
} else {
assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
}
}
-void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
- Decl *Inst) {
+void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
+ ParmVarDecl *Inst) {
D = getCanonicalParmVarDecl(D);
DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>();
Pack->push_back(Inst);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index aff2d1c96676..7a452af77839 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -813,6 +813,14 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
Enum->setAccess(D->getAccess());
// Forward the mangling number from the template to the instantiated decl.
SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D));
+ // See if the old tag was defined along with a declarator.
+ // If it did, mark the new tag as being associated with that declarator.
+ if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D))
+ SemaRef.Context.addDeclaratorForUnnamedTagDecl(Enum, DD);
+ // See if the old tag was defined along with a typedef.
+ // If it did, mark the new tag as being associated with that typedef.
+ if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D))
+ SemaRef.Context.addTypedefNameForUnnamedTagDecl(Enum, TND);
if (SubstQualifier(D, Enum)) return nullptr;
Owner->addDecl(Enum);
@@ -827,7 +835,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
SemaRef.SubstType(TI->getType(), TemplateArgs,
UnderlyingLoc, DeclarationName());
SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(),
- DefnUnderlying, Enum);
+ DefnUnderlying,
+ /*EnumUnderlyingIsImplicit=*/false, Enum);
}
}
@@ -913,6 +922,11 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
llvm_unreachable("EnumConstantDecls can only occur within EnumDecls.");
}
+Decl *
+TemplateDeclInstantiator::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
+ llvm_unreachable("BuiltinTemplateDecls cannot be instantiated.");
+}
+
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
@@ -1143,6 +1157,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
VarDecl *VarInst =
cast_or_null<VarDecl>(VisitVarDecl(Pattern,
/*InstantiatingVarTemplate=*/true));
+ if (!VarInst) return nullptr;
DeclContext *DC = Owner;
@@ -1297,6 +1312,16 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
SemaRef.Context.setManglingNumber(Record,
SemaRef.Context.getManglingNumber(D));
+ // See if the old tag was defined along with a declarator.
+ // If it did, mark the new tag as being associated with that declarator.
+ if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D))
+ SemaRef.Context.addDeclaratorForUnnamedTagDecl(Record, DD);
+
+ // See if the old tag was defined along with a typedef.
+ // If it did, mark the new tag as being associated with that typedef.
+ if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D))
+ SemaRef.Context.addTypedefNameForUnnamedTagDecl(Record, TND);
+
Owner->addDecl(Record);
// DR1484 clarifies that the members of a local class are instantiated as part
@@ -1657,7 +1682,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
SmallVector<TemplateParameterList *, 4> TempParamLists;
unsigned NumTempParamLists = 0;
if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) {
- TempParamLists.set_size(NumTempParamLists);
+ TempParamLists.resize(NumTempParamLists);
for (unsigned I = 0; I != NumTempParamLists; ++I) {
TemplateParameterList *TempParams = D->getTemplateParameterList(I);
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
@@ -1809,9 +1834,9 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// context (which will be a namespace scope) as the template.
if (isFriend) {
if (NumTempParamLists)
- Method->setTemplateParameterListsInfo(SemaRef.Context,
- NumTempParamLists,
- TempParamLists.data());
+ Method->setTemplateParameterListsInfo(
+ SemaRef.Context,
+ llvm::makeArrayRef(TempParamLists.data(), NumTempParamLists));
Method->setLexicalDeclContext(Owner);
Method->setObjectOfFriendDecl();
@@ -2742,7 +2767,7 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
TemplateParameterList *InstL
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
- L->getLAngleLoc(), &Params.front(), N,
+ L->getLAngleLoc(), Params,
L->getRAngleLoc());
return InstL;
}
@@ -3246,16 +3271,11 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// exception specification.
// DR1484: Local classes and their members are instantiated along with the
// containing function.
- bool RequireInstantiation = false;
- if (CXXRecordDecl *Cls = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext())) {
- if (Cls->isLocalClass())
- RequireInstantiation = true;
- }
if (SemaRef.getLangOpts().CPlusPlus11 &&
EPI.ExceptionSpec.Type != EST_None &&
EPI.ExceptionSpec.Type != EST_DynamicNone &&
EPI.ExceptionSpec.Type != EST_BasicNoexcept &&
- !RequireInstantiation) {
+ !Tmpl->isLexicallyWithinFunctionOrMethod()) {
FunctionDecl *ExceptionSpecTemplate = Tmpl;
if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
@@ -3619,19 +3639,6 @@ void Sema::BuildVariableInstantiation(
NewVar->setReferenced(OldVar->isReferenced());
}
- // See if the old variable had a type-specifier that defined an anonymous tag.
- // If it did, mark the new variable as being the declarator for the new
- // anonymous tag.
- if (const TagType *OldTagType = OldVar->getType()->getAs<TagType>()) {
- TagDecl *OldTag = OldTagType->getDecl();
- if (OldTag->getDeclaratorForAnonDecl() == OldVar) {
- TagDecl *NewTag = NewVar->getType()->castAs<TagType>()->getDecl();
- assert(!NewTag->hasNameForLinkage() &&
- !NewTag->hasDeclaratorForAnonDecl());
- NewTag->setDeclaratorForAnonDecl(NewVar);
- }
- }
-
InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope);
LookupResult Previous(
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index fd3ba3549b4c..61052f06c834 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -737,6 +737,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_interface:
case TST_class:
case TST_auto:
+ case TST_auto_type:
case TST_decltype_auto:
case TST_unknown_anytype:
case TST_error:
@@ -867,8 +868,8 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
MarkAnyDeclReferenced(OpLoc, ParameterPack, true);
- return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc,
- ParameterPack, NameLoc, RParenLoc);
+ return SizeOfPackExpr::Create(Context, OpLoc, ParameterPack, NameLoc,
+ RParenLoc);
}
TemplateArgumentLoc
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 02a31ef8d79c..c70568c23b57 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -26,7 +26,6 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
@@ -211,10 +210,8 @@ namespace {
/// Diagnose all the ignored type attributes, given that the
/// declarator worked out to the given type.
void diagnoseIgnoredTypeAttrs(QualType type) const {
- for (SmallVectorImpl<AttributeList*>::const_iterator
- i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
- i != e; ++i)
- diagnoseBadTypeAttribute(getSema(), **i, type);
+ for (auto *Attr : ignoredTypeAttrs)
+ diagnoseBadTypeAttribute(getSema(), *Attr, type);
}
~TypeProcessingState() {
@@ -702,7 +699,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*VolatileQualifierLoc=*/NoLoc,
/*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc, EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
@@ -792,18 +789,33 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
TypeSourceInfo *typeArgInfo = typeArgs[i];
QualType typeArg = typeArgInfo->getType();
- // Type arguments cannot explicitly specify nullability.
- if (auto nullability = AttributedType::stripOuterNullability(typeArg)) {
- SourceLocation nullabilityLoc
- = typeArgInfo->getTypeLoc().findNullabilityLoc();
- SourceLocation diagLoc = nullabilityLoc.isValid()? nullabilityLoc
- : typeArgInfo->getTypeLoc().getLocStart();
- S.Diag(diagLoc,
- diag::err_type_arg_explicit_nullability)
- << typeArg
- << FixItHint::CreateRemoval(nullabilityLoc);
+ // Type arguments cannot have explicit qualifiers or nullability.
+ // We ignore indirect sources of these, e.g. behind typedefs or
+ // template arguments.
+ if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) {
+ bool diagnosed = false;
+ SourceRange rangeToRemove;
+ if (auto attr = qual.getAs<AttributedTypeLoc>()) {
+ rangeToRemove = attr.getLocalSourceRange();
+ if (attr.getTypePtr()->getImmediateNullability()) {
+ typeArg = attr.getTypePtr()->getModifiedType();
+ S.Diag(attr.getLocStart(),
+ diag::err_objc_type_arg_explicit_nullability)
+ << typeArg << FixItHint::CreateRemoval(rangeToRemove);
+ diagnosed = true;
+ }
+ }
+
+ if (!diagnosed) {
+ S.Diag(qual.getLocStart(), diag::err_objc_type_arg_qualified)
+ << typeArg << typeArg.getQualifiers().getAsString()
+ << FixItHint::CreateRemoval(rangeToRemove);
+ }
}
+ // Remove qualifiers even if they're non-local.
+ typeArg = typeArg.getUnqualifiedType();
+
finalTypeArgs.push_back(typeArg);
if (typeArg->getAs<PackExpansionType>())
@@ -1377,11 +1389,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
if (Result.isNull()) {
declarator.setInvalidType(true);
} else if (S.getLangOpts().OpenCL) {
- if (const AtomicType *AT = Result->getAs<AtomicType>()) {
- const BuiltinType *BT = AT->getValueType()->getAs<BuiltinType>();
- bool NoExtTypes = BT && (BT->getKind() == BuiltinType::Int ||
- BT->getKind() == BuiltinType::UInt ||
- BT->getKind() == BuiltinType::Float);
+ if (Result->getAs<AtomicType>()) {
+ StringRef TypeName = Result.getBaseTypeIdentifier()->getName();
+ bool NoExtTypes =
+ llvm::StringSwitch<bool>(TypeName)
+ .Cases("atomic_int", "atomic_uint", "atomic_float",
+ "atomic_flag", true)
+ .Default(false);
if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
<< Result << "cl_khr_int64_base_atomics";
@@ -1393,12 +1407,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
<< Result << "cl_khr_int64_extended_atomics";
declarator.setInvalidType(true);
}
- if (!S.getOpenCLOptions().cl_khr_fp64 && BT &&
- BT->getKind() == BuiltinType::Double) {
+ if (!S.getOpenCLOptions().cl_khr_fp64 &&
+ !TypeName.compare("atomic_double")) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
<< Result << "cl_khr_fp64";
declarator.setInvalidType(true);
}
+ } else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing &&
+ (Result->isImage2dMSAAT() || Result->isImage2dArrayMSAAT() ||
+ Result->isImage2dArrayMSAATDepth() ||
+ Result->isImage2dMSAATDepth())) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
+ << Result << "cl_khr_gl_msaa_sharing";
+ declarator.setInvalidType(true);
}
}
@@ -1482,14 +1503,17 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// template type parameter.
Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
} else {
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false);
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
}
break;
+ case DeclSpec::TST_auto_type:
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false);
+ break;
+
case DeclSpec::TST_decltype_auto:
- Result = Context.getAutoType(QualType(),
- /*decltype(auto)*/true,
- /*IsDependent*/ false);
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto,
+ /*IsDependent*/ false);
break;
case DeclSpec::TST_unknown_anytype:
@@ -1540,8 +1564,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Apply any type attributes from the decl spec. This may cause the
// list of type attributes to be temporarily saved while the type
// attributes are pushed around.
- if (AttributeList *attrs = DS.getAttributes().getList())
- processTypeAttrs(state, Result, TAL_DeclSpec, attrs);
+ processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -1975,7 +1998,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
if (!MPTy->getClass()->isDependentType())
- RequireCompleteType(Loc, T, 0);
+ (void)isCompleteType(Loc, T);
} else {
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
@@ -2103,12 +2126,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (T->isVariableArrayType()) {
// Prohibit the use of non-POD types in VLAs.
QualType BaseT = Context.getBaseElementType(T);
- if (!T->isDependentType() &&
- !RequireCompleteType(Loc, BaseT, 0) &&
- !BaseT.isPODType(Context) &&
- !BaseT->isObjCLifetimeType()) {
- Diag(Loc, diag::err_vla_non_pod)
- << BaseT;
+ if (!T->isDependentType() && isCompleteType(Loc, BaseT) &&
+ !BaseT.isPODType(Context) && !BaseT->isObjCLifetimeType()) {
+ Diag(Loc, diag::err_vla_non_pod) << BaseT;
return QualType();
}
// Prohibit the use of VLAs during template argument deduction.
@@ -2122,7 +2142,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
} else if (ASM != ArrayType::Normal || Quals != 0)
Diag(Loc,
getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
- : diag::ext_c99_array_usage) << ASM;
+ : diag::ext_c99_array_usage) << ASM;
}
if (T->isVariableArrayType()) {
@@ -2271,8 +2291,11 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
// Adjust the default free function calling convention to the default method
// calling convention.
+ bool IsCtorOrDtor =
+ (Entity.getNameKind() == DeclarationName::CXXConstructorName) ||
+ (Entity.getNameKind() == DeclarationName::CXXDestructorName);
if (T->isFunctionType())
- adjustMemberFunctionCC(T, /*IsStatic=*/false);
+ adjustMemberFunctionCC(T, /*IsStatic=*/false, IsCtorOrDtor, Loc);
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -2432,14 +2455,14 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
return;
struct Qual {
- unsigned Mask;
const char *Name;
+ unsigned Mask;
SourceLocation Loc;
} const QualKinds[4] = {
- { DeclSpec::TQ_const, "const", ConstQualLoc },
- { DeclSpec::TQ_volatile, "volatile", VolatileQualLoc },
- { DeclSpec::TQ_restrict, "restrict", RestrictQualLoc },
- { DeclSpec::TQ_atomic, "_Atomic", AtomicQualLoc }
+ { "const", DeclSpec::TQ_const, ConstQualLoc },
+ { "volatile", DeclSpec::TQ_volatile, VolatileQualLoc },
+ { "restrict", DeclSpec::TQ_restrict, RestrictQualLoc },
+ { "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc }
};
SmallString<32> QualStr;
@@ -2455,7 +2478,7 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
// If we have a location for the qualifier, offer a fixit.
SourceLocation QualLoc = QualKinds[I].Loc;
- if (!QualLoc.isInvalid()) {
+ if (QualLoc.isValid()) {
FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc);
if (Loc.isInvalid() ||
getSourceManager().isBeforeInTranslationUnit(QualLoc, Loc))
@@ -2548,8 +2571,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// The TagDecl owned by the DeclSpec.
TagDecl *OwnedTagDecl = nullptr;
- bool ContainsPlaceholderType = false;
-
switch (D.getName().getKind()) {
case UnqualifiedId::IK_ImplicitSelfParam:
case UnqualifiedId::IK_OperatorFunctionId:
@@ -2557,7 +2578,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
T = ConvertDeclSpecToType(state);
- ContainsPlaceholderType = D.getDeclSpec().containsPlaceholderType();
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
@@ -2572,8 +2592,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// Constructors and destructors don't have return types. Use
// "void" instead.
T = SemaRef.Context.VoidTy;
- if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList())
- processTypeAttrs(state, T, TAL_DeclSpec, attrs);
+ processTypeAttrs(state, T, TAL_DeclSpec,
+ D.getDeclSpec().getAttributes().getList());
break;
case UnqualifiedId::IK_ConversionFunctionId:
@@ -2581,7 +2601,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// converts to.
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
&ReturnTypeInfo);
- ContainsPlaceholderType = T->getContainedAutoType();
break;
}
@@ -2589,17 +2608,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
distributeTypeAttrsFromDeclarator(state, T);
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
- // In C++11, a function declarator using 'auto' must have a trailing return
- // type (this is checked later) and we can skip this. In other languages
- // using auto, we need to check regardless.
- // C++14 In generic lambdas allow 'auto' in their parameters.
- if (ContainsPlaceholderType &&
- (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
+ if (D.getDeclSpec().containsPlaceholderType()) {
int Error = -1;
switch (D.getContext()) {
- case Declarator::KNRTypeListContext:
- llvm_unreachable("K&R type lists aren't allowed in C++");
case Declarator::LambdaExprContext:
llvm_unreachable("Can't specify a type specifier in lambda grammar");
case Declarator::ObjCParameterContext:
@@ -2608,69 +2620,88 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 0;
break;
case Declarator::LambdaExprParameterContext:
+ // In C++14, generic lambdas allow 'auto' in their parameters.
if (!(SemaRef.getLangOpts().CPlusPlus14
&& D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
- Error = 14;
+ Error = 16;
break;
- case Declarator::MemberContext:
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
+ case Declarator::MemberContext: {
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
+ D.isFunctionDeclarator())
break;
+ bool Cxx = SemaRef.getLangOpts().CPlusPlus;
switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
case TTK_Enum: llvm_unreachable("unhandled tag kind");
- case TTK_Struct: Error = 1; /* Struct member */ break;
- case TTK_Union: Error = 2; /* Union member */ break;
- case TTK_Class: Error = 3; /* Class member */ break;
- case TTK_Interface: Error = 4; /* Interface member */ break;
+ case TTK_Struct: Error = Cxx ? 1 : 2; /* Struct member */ break;
+ case TTK_Union: Error = Cxx ? 3 : 4; /* Union member */ break;
+ case TTK_Class: Error = 5; /* Class member */ break;
+ case TTK_Interface: Error = 6; /* Interface member */ break;
}
break;
+ }
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
- Error = 5; // Exception declaration
+ Error = 7; // Exception declaration
break;
case Declarator::TemplateParamContext:
- Error = 6; // Template parameter
+ Error = 8; // Template parameter
break;
case Declarator::BlockLiteralContext:
- Error = 7; // Block literal
+ Error = 9; // Block literal
break;
case Declarator::TemplateTypeArgContext:
- Error = 8; // Template type argument
+ Error = 10; // Template type argument
break;
case Declarator::AliasDeclContext:
case Declarator::AliasTemplateContext:
- Error = 10; // Type alias
+ Error = 12; // Type alias
break;
case Declarator::TrailingReturnContext:
- if (!SemaRef.getLangOpts().CPlusPlus14)
- Error = 11; // Function return type
+ if (!SemaRef.getLangOpts().CPlusPlus14 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 13; // Function return type
break;
case Declarator::ConversionIdContext:
- if (!SemaRef.getLangOpts().CPlusPlus14)
- Error = 12; // conversion-type-id
+ if (!SemaRef.getLangOpts().CPlusPlus14 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 14; // conversion-type-id
break;
case Declarator::TypeNameContext:
- Error = 13; // Generic
+ Error = 15; // Generic
break;
case Declarator::FileContext:
case Declarator::BlockContext:
case Declarator::ForContext:
case Declarator::ConditionContext:
+ break;
case Declarator::CXXNewContext:
+ if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 17; // 'new' type
+ break;
+ case Declarator::KNRTypeListContext:
+ Error = 18; // K&R function parameter
break;
}
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- Error = 9;
-
- // In Objective-C it is an error to use 'auto' on a function declarator.
- if (D.isFunctionDeclarator())
Error = 11;
+ // In Objective-C it is an error to use 'auto' on a function declarator
+ // (and everywhere for '__auto_type').
+ if (D.isFunctionDeclarator() &&
+ (!SemaRef.getLangOpts().CPlusPlus11 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type))
+ Error = 13;
+
+ bool HaveTrailing = false;
+
// C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
// contains a trailing return type. That is only legal at the outermost
// level. Check all declarator chunks (outermost first) anyway, to give
// better diagnostics.
- if (SemaRef.getLangOpts().CPlusPlus11 && Error != -1) {
+ // We don't support '__auto_type' with trailing return types.
+ if (SemaRef.getLangOpts().CPlusPlus11 &&
+ D.getDeclSpec().getTypeSpecType() != DeclSpec::TST_auto_type) {
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
@@ -2678,6 +2709,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (DeclType.Kind == DeclaratorChunk::Function) {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
if (FTI.hasTrailingReturnType()) {
+ HaveTrailing = true;
Error = -1;
break;
}
@@ -2690,22 +2722,31 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
- const bool IsDeclTypeAuto =
- D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto;
+ unsigned Keyword;
+ switch (D.getDeclSpec().getTypeSpecType()) {
+ case DeclSpec::TST_auto: Keyword = 0; break;
+ case DeclSpec::TST_decltype_auto: Keyword = 1; break;
+ case DeclSpec::TST_auto_type: Keyword = 2; break;
+ default: llvm_unreachable("unknown auto TypeSpecType");
+ }
SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
- << IsDeclTypeAuto << Error << AutoRange;
+ << Keyword << Error << AutoRange;
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
- } else
+ } else if (!HaveTrailing) {
+ // If there was a trailing return type, we already got
+ // warn_cxx98_compat_trailing_return_type in the parser.
SemaRef.Diag(AutoRange.getBegin(),
diag::warn_cxx98_compat_auto_type_specifier)
<< AutoRange;
+ }
}
if (SemaRef.getLangOpts().CPlusPlus &&
OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) {
// Check the contexts where C++ forbids the declaration of a new class
// or enumeration in a type-specifier-seq.
+ unsigned DiagID = 0;
switch (D.getContext()) {
case Declarator::TrailingReturnContext:
// Class and enumeration definitions are syntactically not allowed in
@@ -2725,10 +2766,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::AliasDeclContext:
break;
case Declarator::AliasTemplateContext:
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_alias_template)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- D.setInvalidType(true);
+ DiagID = diag::err_type_defined_in_alias_template;
break;
case Declarator::TypeNameContext:
case Declarator::ConversionIdContext:
@@ -2737,10 +2775,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
case Declarator::TemplateTypeArgContext:
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_type_specifier)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- D.setInvalidType(true);
+ DiagID = diag::err_type_defined_in_type_specifier;
break;
case Declarator::PrototypeContext:
case Declarator::LambdaExprParameterContext:
@@ -2749,20 +2784,21 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::KNRTypeListContext:
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_param_type)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- D.setInvalidType(true);
+ DiagID = diag::err_type_defined_in_param_type;
break;
case Declarator::ConditionContext:
// C++ 6.4p2:
// The type-specifier-seq shall not contain typedef and shall not declare
// a new class or enumeration.
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_condition);
- D.setInvalidType(true);
+ DiagID = diag::err_type_defined_in_condition;
break;
}
+
+ if (DiagID != 0) {
+ SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID)
+ << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+ D.setInvalidType(true);
+ }
}
assert(!T.isNull() && "This function should not return a null type");
@@ -3286,14 +3322,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Are we in an assume-nonnull region?
bool inAssumeNonNullRegion = false;
- if (S.PP.getPragmaAssumeNonNullLoc().isValid() &&
- !state.getDeclarator().isObjCWeakProperty() &&
- !S.deduceWeakPropertyFromType(T)) {
+ if (S.PP.getPragmaAssumeNonNullLoc().isValid()) {
inAssumeNonNullRegion = true;
// Determine which file we saw the assume-nonnull region in.
FileID file = getNullabilityCompletenessCheckFileID(
S, S.PP.getPragmaAssumeNonNullLoc());
- if (!file.isInvalid()) {
+ if (file.isValid()) {
FileNullability &fileNullability = S.NullabilityMap[file];
// If we haven't seen any type nullability before, now we have.
@@ -3367,6 +3401,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
complainAboutMissingNullability = CAMN_No;
break;
}
+
+ // Weak properties are inferred to be nullable.
+ if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
+ inferNullability = NullabilityKind::Nullable;
+ break;
+ }
+
// fallthrough
case Declarator::FileContext:
@@ -3699,7 +3740,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
} else if (D.getContext() != Declarator::LambdaExprContext &&
(T.hasQualifiers() || !isa<AutoType>(T) ||
- cast<AutoType>(T)->isDecltypeAuto())) {
+ cast<AutoType>(T)->getKeyword() != AutoTypeKeyword::Auto)) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
@@ -3835,9 +3876,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Exception specs are not allowed in typedefs. Complain, but add it
// anyway.
if (IsTypedefName && FTI.getExceptionSpecType())
- S.Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef)
- << (D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext);
+ S.Diag(FTI.getExceptionSpecLocBeg(),
+ diag::err_exception_spec_in_typedef)
+ << (D.getContext() == Declarator::AliasDeclContext ||
+ D.getContext() == Declarator::AliasTemplateContext);
// If we see "T var();" or "T var(T());" at block scope, it is probably
// an attempt to initialize a variable, not a function declaration.
@@ -4062,8 +4104,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// See if there are any attributes on this declarator chunk.
- if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
- processTypeAttrs(state, T, TAL_DeclChunk, attrs);
+ processTypeAttrs(state, T, TAL_DeclChunk,
+ const_cast<AttributeList *>(DeclType.getAttrs()));
}
assert(!T.isNull() && "T must not be null after this point");
@@ -4156,8 +4198,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// Apply any undistributed attributes from the declarator.
- if (AttributeList *attrs = D.getAttributes())
- processTypeAttrs(state, T, TAL_DeclName, attrs);
+ processTypeAttrs(state, T, TAL_DeclName, D.getAttributes());
// Diagnose any ignored type attributes.
state.diagnoseIgnoredTypeAttrs(T);
@@ -4377,7 +4418,7 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (getLangOpts().ObjCAutoRefCount) {
+ if (getLangOpts().ObjC1) {
Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
if (ownership != Qualifiers::OCL_None)
transferARCOwnership(state, declSpecTy, ownership);
@@ -4402,6 +4443,7 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
case AttributedType::attr_objc_gc:
return AttributeList::AT_ObjCGC;
case AttributedType::attr_objc_ownership:
+ case AttributedType::attr_objc_inert_unsafe_unretained:
return AttributeList::AT_ObjCOwnership;
case AttributedType::attr_noreturn:
return AttributeList::AT_NoReturn;
@@ -5061,11 +5103,6 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
return true;
}
- // Consume lifetime attributes without further comment outside of
- // ARC mode.
- if (!S.getLangOpts().ObjCAutoRefCount)
- return true;
-
IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
Qualifiers::ObjCLifetime lifetime;
if (II->isStr("none"))
@@ -5083,6 +5120,14 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
return true;
}
+ // Just ignore lifetime attributes other than __weak and __unsafe_unretained
+ // outside of ARC mode.
+ if (!S.getLangOpts().ObjCAutoRefCount &&
+ lifetime != Qualifiers::OCL_Weak &&
+ lifetime != Qualifiers::OCL_ExplicitNone) {
+ return true;
+ }
+
SplitQualType underlyingType = type.split();
// Check for redundant/conflicting ownership qualifiers.
@@ -5123,6 +5168,25 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
<< TDS_ObjCObjOrBlock << type;
}
+ // Don't actually add the __unsafe_unretained qualifier in non-ARC files,
+ // because having both 'T' and '__unsafe_unretained T' exist in the type
+ // system causes unfortunate widespread consistency problems. (For example,
+ // they're not considered compatible types, and we mangle them identicially
+ // as template arguments.) These problems are all individually fixable,
+ // but it's easier to just not add the qualifier and instead sniff it out
+ // in specific places using isObjCInertUnsafeUnretainedType().
+ //
+ // Doing this does means we miss some trivial consistency checks that
+ // would've triggered in ARC, but that's better than trying to solve all
+ // the coexistence problems with __unsafe_unretained.
+ if (!S.getLangOpts().ObjCAutoRefCount &&
+ lifetime == Qualifiers::OCL_ExplicitNone) {
+ type = S.Context.getAttributedType(
+ AttributedType::attr_objc_inert_unsafe_unretained,
+ type, type);
+ return true;
+ }
+
QualType origType = type;
if (!NonObjCPointer)
type = S.Context.getQualifiedType(underlyingType);
@@ -5133,19 +5197,29 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
origType, type);
- // Forbid __weak if the runtime doesn't support it.
- if (lifetime == Qualifiers::OCL_Weak &&
- !S.getLangOpts().ObjCARCWeak && !NonObjCPointer) {
-
- // Actually, delay this until we know what we're parsing.
+ auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
+ unsigned diagnostic, QualType type) {
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
sema::DelayedDiagnostic::makeForbiddenType(
- S.getSourceManager().getExpansionLoc(AttrLoc),
- diag::err_arc_weak_no_runtime, type, /*ignored*/ 0));
+ S.getSourceManager().getExpansionLoc(loc),
+ diagnostic, type, /*ignored*/ 0));
} else {
- S.Diag(AttrLoc, diag::err_arc_weak_no_runtime);
+ S.Diag(loc, diagnostic);
}
+ };
+
+ // Sometimes, __weak isn't allowed.
+ if (lifetime == Qualifiers::OCL_Weak &&
+ !S.getLangOpts().ObjCWeak && !NonObjCPointer) {
+
+ // Use a specialized diagnostic if the runtime just doesn't support them.
+ unsigned diagnostic =
+ (S.getLangOpts().ObjCWeakRuntime ? diag::err_arc_weak_disabled
+ : diag::err_arc_weak_no_runtime);
+
+ // In any case, delay the diagnostic until we know what we're parsing.
+ diagnoseOrDelay(S, AttrLoc, diagnostic, type);
attr.setInvalid();
return true;
@@ -5158,9 +5232,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
type->getAs<ObjCObjectPointerType>()) {
if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) {
if (Class->isArcWeakrefUnavailable()) {
- S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
- S.Diag(ObjT->getInterfaceDecl()->getLocation(),
- diag::note_class_declared);
+ S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
+ S.Diag(ObjT->getInterfaceDecl()->getLocation(),
+ diag::note_class_declared);
}
}
}
@@ -5402,9 +5476,12 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
// Pointer type qualifiers can only operate on pointer types, but not
// pointer-to-member types.
if (!isa<PointerType>(Desugared)) {
- S.Diag(Attr.getLoc(), Type->isMemberPointerType() ?
- diag::err_attribute_no_member_pointers :
- diag::err_attribute_pointers_only) << Attr.getName();
+ if (Type->isMemberPointerType())
+ S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers)
+ << Attr.getName();
+ else
+ S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
+ << Attr.getName() << 0;
return true;
}
@@ -5843,25 +5920,41 @@ bool Sema::hasExplicitCallingConv(QualType &T) {
return false;
}
-void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
+void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
+ SourceLocation Loc) {
FunctionTypeUnwrapper Unwrapped(*this, T);
const FunctionType *FT = Unwrapped.get();
bool IsVariadic = (isa<FunctionProtoType>(FT) &&
cast<FunctionProtoType>(FT)->isVariadic());
-
- // Only adjust types with the default convention. For example, on Windows we
- // should adjust a __cdecl type to __thiscall for instance methods, and a
- // __thiscall type to __cdecl for static methods.
CallingConv CurCC = FT->getCallConv();
- CallingConv FromCC =
- Context.getDefaultCallingConvention(IsVariadic, IsStatic);
CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
- if (CurCC != FromCC || FromCC == ToCC)
- return;
- if (hasExplicitCallingConv(T))
+ if (CurCC == ToCC)
return;
+ // MS compiler ignores explicit calling convention attributes on structors. We
+ // should do the same.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() && IsCtorOrDtor) {
+ // Issue a warning on ignored calling convention -- except of __stdcall.
+ // Again, this is what MS compiler does.
+ if (CurCC != CC_X86StdCall)
+ Diag(Loc, diag::warn_cconv_structors)
+ << FunctionType::getNameForCallConv(CurCC);
+ // Default adjustment.
+ } else {
+ // Only adjust types with the default convention. For example, on Windows
+ // we should adjust a __cdecl type to __thiscall for instance methods, and a
+ // __thiscall type to __cdecl for static methods.
+ CallingConv DefaultCC =
+ Context.getDefaultCallingConvention(IsVariadic, IsStatic);
+
+ if (CurCC != DefaultCC || DefaultCC == ToCC)
+ return;
+
+ if (hasExplicitCallingConv(T))
+ return;
+ }
+
FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
QualType Wrapped = Unwrapped.wrap(*this, FT);
T = Context.getAdjustedType(T, Wrapped);
@@ -6077,10 +6170,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
- AttributeList *next;
- do {
+ bool hasOpenCLAddressSpace = false;
+ while (attrs) {
AttributeList &attr = *attrs;
- next = attr.getNext();
+ attrs = attr.getNext(); // reset to the next here due to early loop continue
+ // stmts
// Skip attributes that were marked to be invalid.
if (attr.isInvalid())
@@ -6139,6 +6233,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
+ hasOpenCLAddressSpace = true;
break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type))
@@ -6233,7 +6328,83 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
distributeFunctionTypeAttr(state, attr, type);
break;
}
- } while ((attrs = next));
+ }
+
+ // If address space is not set, OpenCL 2.0 defines non private default
+ // address spaces for some cases:
+ // OpenCL 2.0, section 6.5:
+ // The address space for a variable at program scope or a static variable
+ // inside a function can either be __global or __constant, but defaults to
+ // __global if not specified.
+ // (...)
+ // Pointers that are declared without pointing to a named address space point
+ // to the generic address space.
+ if (state.getSema().getLangOpts().OpenCLVersion >= 200 &&
+ !hasOpenCLAddressSpace && type.getAddressSpace() == 0 &&
+ (TAL == TAL_DeclSpec || TAL == TAL_DeclChunk)) {
+ Declarator &D = state.getDeclarator();
+ if (state.getCurrentChunkIndex() > 0 &&
+ D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind ==
+ DeclaratorChunk::Pointer) {
+ type = state.getSema().Context.getAddrSpaceQualType(
+ type, LangAS::opencl_generic);
+ } else if (state.getCurrentChunkIndex() == 0 &&
+ D.getContext() == Declarator::FileContext &&
+ !D.isFunctionDeclarator() && !D.isFunctionDefinition() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ !type->isSamplerT())
+ type = state.getSema().Context.getAddrSpaceQualType(
+ type, LangAS::opencl_global);
+ else if (state.getCurrentChunkIndex() == 0 &&
+ D.getContext() == Declarator::BlockContext &&
+ D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
+ type = state.getSema().Context.getAddrSpaceQualType(
+ type, LangAS::opencl_global);
+ }
+}
+
+void Sema::completeExprArrayBound(Expr *E) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+ if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
+ SourceLocation PointOfInstantiation = E->getExprLoc();
+
+ if (MemberSpecializationInfo *MSInfo =
+ Var->getMemberSpecializationInfo()) {
+ // If we don't already have a point of instantiation, this is it.
+ if (MSInfo->getPointOfInstantiation().isInvalid()) {
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+
+ // This is a modification of an existing AST node. Notify
+ // listeners.
+ if (ASTMutationListener *L = getASTMutationListener())
+ L->StaticDataMemberInstantiated(Var);
+ }
+ } else {
+ VarTemplateSpecializationDecl *VarSpec =
+ cast<VarTemplateSpecializationDecl>(Var);
+ if (VarSpec->getPointOfInstantiation().isInvalid())
+ VarSpec->setPointOfInstantiation(PointOfInstantiation);
+ }
+
+ InstantiateVariableDefinition(PointOfInstantiation, Var);
+
+ // Update the type to the newly instantiated definition's type both
+ // here and within the expression.
+ if (VarDecl *Def = Var->getDefinition()) {
+ DRE->setDecl(Def);
+ QualType T = Def->getType();
+ DRE->setType(T);
+ // FIXME: Update the type on all intervening expressions.
+ E->setType(T);
+ }
+
+ // We still go on to try to complete the type independently, as it
+ // may also require instantiations or diagnostics if it remains
+ // incomplete.
+ }
+ }
+ }
}
/// \brief Ensure that the type of the given expression is complete.
@@ -6250,87 +6421,26 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
///
/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
/// otherwise.
-bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){
+bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser) {
QualType T = E->getType();
- // Fast path the case where the type is already complete.
- if (!T->isIncompleteType())
- // FIXME: The definition might not be visible.
- return false;
-
// Incomplete array types may be completed by the initializer attached to
// their definitions. For static data members of class templates and for
// variable templates, we need to instantiate the definition to get this
// initializer and complete the type.
if (T->isIncompleteArrayType()) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
- if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
- SourceLocation PointOfInstantiation = E->getExprLoc();
-
- if (MemberSpecializationInfo *MSInfo =
- Var->getMemberSpecializationInfo()) {
- // If we don't already have a point of instantiation, this is it.
- if (MSInfo->getPointOfInstantiation().isInvalid()) {
- MSInfo->setPointOfInstantiation(PointOfInstantiation);
-
- // This is a modification of an existing AST node. Notify
- // listeners.
- if (ASTMutationListener *L = getASTMutationListener())
- L->StaticDataMemberInstantiated(Var);
- }
- } else {
- VarTemplateSpecializationDecl *VarSpec =
- cast<VarTemplateSpecializationDecl>(Var);
- if (VarSpec->getPointOfInstantiation().isInvalid())
- VarSpec->setPointOfInstantiation(PointOfInstantiation);
- }
-
- InstantiateVariableDefinition(PointOfInstantiation, Var);
-
- // Update the type to the newly instantiated definition's type both
- // here and within the expression.
- if (VarDecl *Def = Var->getDefinition()) {
- DRE->setDecl(Def);
- T = Def->getType();
- DRE->setType(T);
- E->setType(T);
- }
-
- // We still go on to try to complete the type independently, as it
- // may also require instantiations or diagnostics if it remains
- // incomplete.
- }
- }
- }
+ completeExprArrayBound(E);
+ T = E->getType();
}
// FIXME: Are there other cases which require instantiating something other
// than the type to complete the type of an expression?
- // Look through reference types and complete the referred type.
- if (const ReferenceType *Ref = T->getAs<ReferenceType>())
- T = Ref->getPointeeType();
-
return RequireCompleteType(E->getExprLoc(), T, Diagnoser);
}
-namespace {
- struct TypeDiagnoserDiag : Sema::TypeDiagnoser {
- unsigned DiagID;
-
- TypeDiagnoserDiag(unsigned DiagID)
- : Sema::TypeDiagnoser(DiagID == 0), DiagID(DiagID) {}
-
- void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
- if (Suppressed) return;
- S.Diag(Loc, DiagID) << T;
- }
- };
-}
-
bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
- TypeDiagnoserDiag Diagnoser(DiagID);
+ BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireCompleteExprType(E, Diagnoser);
}
@@ -6353,7 +6463,7 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
/// @c false otherwise.
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
- if (RequireCompleteTypeImpl(Loc, T, Diagnoser))
+ if (RequireCompleteTypeImpl(Loc, T, &Diagnoser))
return true;
if (const TagType *Tag = T->getAs<TagType>()) {
if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
@@ -6457,7 +6567,7 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
/// \brief The implementation of RequireCompleteType
bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser) {
+ TypeDiagnoser *Diagnoser) {
// FIXME: Add this assertion to make sure we always get instantiation points.
// assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
// FIXME: Add this assertion to help us flush out problems with
@@ -6466,24 +6576,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// assert(!T->isDependentType() &&
// "Can't ask whether a dependent type is complete");
+ // We lock in the inheritance model once somebody has asked us to ensure
+ // that a pointer-to-member type is complete.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+ if (!MPTy->getClass()->isDependentType()) {
+ (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
+ assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
+ }
+ }
+ }
+
// If we have a complete type, we're done.
NamedDecl *Def = nullptr;
if (!T->isIncompleteType(&Def)) {
// If we know about the definition but it is not visible, complain.
NamedDecl *SuggestedDef = nullptr;
- if (!Diagnoser.Suppressed && Def &&
- !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true))
- diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true);
-
- // We lock in the inheritance model once somebody has asked us to ensure
- // that a pointer-to-member type is complete.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
- if (!MPTy->getClass()->isDependentType()) {
- RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
- assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
- }
- }
+ if (Def &&
+ !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) {
+ // If the user is going to see an error here, recover by making the
+ // definition visible.
+ bool TreatAsComplete = Diagnoser && !isSFINAEContext();
+ if (Diagnoser)
+ diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true,
+ /*Recover*/TreatAsComplete);
+ return !TreatAsComplete;
}
return false;
@@ -6500,6 +6617,9 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// chain for a declaration that can be accessed through a mechanism other
// than name lookup (eg, referenced in a template, or a variable whose type
// could be completed by the module)?
+ //
+ // FIXME: Should we map through to the base array element type before
+ // checking for a tag type?
if (Tag || IFace) {
NamedDecl *D =
Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl();
@@ -6530,12 +6650,16 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
= Context.getAsConstantArrayType(MaybeTemplate))
MaybeTemplate = Array->getElementType();
if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
+ bool Instantiated = false;
+ bool Diagnosed = false;
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
- if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
- return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
- TSK_ImplicitInstantiation,
- /*Complain=*/!Diagnoser.Suppressed);
+ if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
+ Diagnosed = InstantiateClassTemplateSpecialization(
+ Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
+ /*Complain=*/Diagnoser);
+ Instantiated = true;
+ }
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
@@ -6543,16 +6667,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo();
assert(MSI && "Missing member specialization information?");
// This record was instantiated from a class within a template.
- if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
- return InstantiateClass(Loc, Rec, Pattern,
- getTemplateInstantiationArgs(Rec),
- TSK_ImplicitInstantiation,
- /*Complain=*/!Diagnoser.Suppressed);
+ if (MSI->getTemplateSpecializationKind() !=
+ TSK_ExplicitSpecialization) {
+ Diagnosed = InstantiateClass(Loc, Rec, Pattern,
+ getTemplateInstantiationArgs(Rec),
+ TSK_ImplicitInstantiation,
+ /*Complain=*/Diagnoser);
+ Instantiated = true;
+ }
}
}
+
+ if (Instantiated) {
+ // Instantiate* might have already complained that the template is not
+ // defined, if we asked it to.
+ if (Diagnoser && Diagnosed)
+ return true;
+ // If we instantiated a definition, check that it's usable, even if
+ // instantiation produced an error, so that repeated calls to this
+ // function give consistent answers.
+ if (!T->isIncompleteType())
+ return RequireCompleteTypeImpl(Loc, T, Diagnoser);
+ }
}
- if (Diagnoser.Suppressed)
+ if (!Diagnoser)
return true;
// We have an incomplete type. Produce a diagnostic.
@@ -6562,7 +6701,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
return true;
}
- Diagnoser.diagnose(*this, Loc, T);
+ Diagnoser->diagnose(*this, Loc, T);
// If the type was a forward declaration of a class/struct/union
// type, produce a note.
@@ -6586,7 +6725,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID) {
- TypeDiagnoserDiag Diagnoser(DiagID);
+ BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireCompleteType(Loc, T, Diagnoser);
}
@@ -6627,14 +6766,10 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
assert(!T->isDependentType() && "type should not be dependent");
QualType ElemType = Context.getBaseElementType(T);
- RequireCompleteType(Loc, ElemType, 0);
-
- if (T->isLiteralType(Context))
+ if ((isCompleteType(Loc, ElemType) || ElemType->isVoidType()) &&
+ T->isLiteralType(Context))
return false;
- if (Diagnoser.Suppressed)
- return true;
-
Diagnoser.diagnose(*this, Loc, T);
if (T->isVariableArrayType())
@@ -6649,10 +6784,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
// A partially-defined class type can't be a literal type, because a literal
// class type must have a trivial destructor (which can't be checked until
// the class definition is complete).
- if (!RD->isCompleteDefinition()) {
- RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T);
+ if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T))
return true;
- }
// If the class has virtual base classes, then it's not an aggregate, and
// cannot have any constexpr constructors or a trivial default constructor,
@@ -6704,7 +6837,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
}
bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
- TypeDiagnoserDiag Diagnoser(DiagID);
+ BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireLiteralType(Loc, T, Diagnoser);
}
@@ -6730,6 +6863,9 @@ QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
if (ER.isInvalid()) return QualType();
E = ER.get();
+ if (!getLangOpts().CPlusPlus && E->refersToBitField())
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
+
if (!E->isTypeDependent()) {
QualType T = E->getType();
if (const TagType *TT = T->getAs<TagType>())
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 6e193a3529c9..e0a9653eb93b 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -21,6 +21,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
@@ -390,7 +391,7 @@ public:
/// due to transformation.
///
/// \returns true if an error occurred, false otherwise.
- bool TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall,
+ bool TransformExprs(Expr *const *Inputs, unsigned NumInputs, bool IsCall,
SmallVectorImpl<Expr *> &Outputs,
bool *ArgChanged = nullptr);
@@ -503,7 +504,8 @@ public:
///
/// Returns true if there was an error.
bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
- TemplateArgumentLoc &Output);
+ TemplateArgumentLoc &Output,
+ bool Uneval = false);
/// \brief Transform the given set of template arguments.
///
@@ -525,8 +527,10 @@ public:
/// Returns true if an error occurred.
bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs,
unsigned NumInputs,
- TemplateArgumentListInfo &Outputs) {
- return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs);
+ TemplateArgumentListInfo &Outputs,
+ bool Uneval = false) {
+ return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs,
+ Uneval);
}
/// \brief Transform the given set of template arguments.
@@ -546,7 +550,8 @@ public:
template<typename InputIterator>
bool TransformTemplateArguments(InputIterator First,
InputIterator Last,
- TemplateArgumentListInfo &Outputs);
+ TemplateArgumentListInfo &Outputs,
+ bool Uneval = false);
/// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
void InventTemplateArgumentLoc(const TemplateArgument &Arg,
@@ -843,11 +848,11 @@ public:
/// \brief Build a new C++11 auto type.
///
/// By default, builds a new AutoType with the given deduced type.
- QualType RebuildAutoType(QualType Deduced, bool IsDecltypeAuto) {
+ QualType RebuildAutoType(QualType Deduced, AutoTypeKeyword Keyword) {
// Note, IsDependent is always false here: we implicitly convert an 'auto'
// which has been deduced to a dependent type into an undeduced 'auto', so
// that we'll retry deduction after the transformation.
- return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto,
+ return SemaRef.Context.getAutoType(Deduced, Keyword,
/*IsDependent*/ false);
}
@@ -1282,6 +1287,30 @@ public:
Constraints, Clobbers, Exprs, EndLoc);
}
+ /// \brief Build a new co_return statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildCoreturnStmt(SourceLocation CoreturnLoc, Expr *Result) {
+ return getSema().BuildCoreturnStmt(CoreturnLoc, Result);
+ }
+
+ /// \brief Build a new co_await expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCoawaitExpr(SourceLocation CoawaitLoc, Expr *Result) {
+ return getSema().BuildCoawaitExpr(CoawaitLoc, Result);
+ }
+
+ /// \brief Build a new co_yield expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCoyieldExpr(SourceLocation CoyieldLoc, Expr *Result) {
+ return getSema().BuildCoyieldExpr(CoyieldLoc, Result);
+ }
+
/// \brief Build a new Objective-C \@try statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1354,12 +1383,15 @@ public:
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *RebuildOMPIfClause(Expr *Condition,
- SourceLocation StartLoc,
+ OMPClause *RebuildOMPIfClause(OpenMPDirectiveKind NameModifier,
+ Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc,
+ SourceLocation ColonLoc,
SourceLocation EndLoc) {
- return getSema().ActOnOpenMPIfClause(Condition, StartLoc,
- LParenLoc, EndLoc);
+ return getSema().ActOnOpenMPIfClause(NameModifier, Condition, StartLoc,
+ LParenLoc, NameModifierLoc, ColonLoc,
+ EndLoc);
}
/// \brief Build a new OpenMP 'final' clause.
@@ -1395,6 +1427,16 @@ public:
return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
}
+ /// \brief Build a new OpenMP 'simdlen' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc);
+ }
+
/// \brief Build a new OpenMP 'collapse' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -1436,15 +1478,24 @@ public:
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *RebuildOMPScheduleClause(OpenMPScheduleClauseKind Kind,
- Expr *ChunkSize,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation KindLoc,
- SourceLocation CommaLoc,
- SourceLocation EndLoc) {
+ OMPClause *RebuildOMPScheduleClause(
+ OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
+ OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+ SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
return getSema().ActOnOpenMPScheduleClause(
- Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
+ M1, M2, Kind, ChunkSize, StartLoc, LParenLoc, M1Loc, M2Loc, KindLoc,
+ CommaLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'ordered' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPOrderedClause(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ SourceLocation LParenLoc, Expr *Num) {
+ return getSema().ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Num);
}
/// \brief Build a new OpenMP 'private' clause.
@@ -1518,10 +1569,13 @@ public:
OMPClause *RebuildOMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
SourceLocation StartLoc,
SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier,
+ SourceLocation ModifierLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPLinearClause(VarList, Step, StartLoc, LParenLoc,
- ColonLoc, EndLoc);
+ Modifier, ModifierLoc, ColonLoc,
+ EndLoc);
}
/// \brief Build a new OpenMP 'aligned' clause.
@@ -1586,6 +1640,97 @@ public:
StartLoc, LParenLoc, EndLoc);
}
+ /// \brief Build a new OpenMP 'device' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPDeviceClause(Expr *Device, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDeviceClause(Device, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'map' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPMapClause(
+ OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType,
+ SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPMapClause(MapTypeModifier, MapType, MapLoc,
+ ColonLoc, VarList,StartLoc,
+ LParenLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'num_teams' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPNumTeamsClause(NumTeams, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'thread_limit' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPThreadLimitClause(Expr *ThreadLimit,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPThreadLimitClause(ThreadLimit, StartLoc,
+ LParenLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'priority' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPPriorityClause(Priority, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'grainsize' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPGrainsizeClause(Expr *Grainsize, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPGrainsizeClause(Grainsize, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'num_tasks' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPNumTasksClause(NumTasks, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'hint' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPHintClause(Expr *Hint, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1673,6 +1818,7 @@ public:
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
SourceLocation ColonLoc,
Stmt *Range, Stmt *BeginEnd,
Expr *Cond, Expr *Inc,
@@ -1695,7 +1841,8 @@ public:
}
}
- return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd,
+ return getSema().BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc,
+ Range, BeginEnd,
Cond, Inc, LoopVar, RParenLoc,
Sema::BFRK_Rebuild);
}
@@ -1808,12 +1955,11 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildOffsetOfExpr(SourceLocation OperatorLoc,
- TypeSourceInfo *Type,
- Sema::OffsetOfComponent *Components,
- unsigned NumComponents,
- SourceLocation RParenLoc) {
+ TypeSourceInfo *Type,
+ ArrayRef<Sema::OffsetOfComponent> Components,
+ SourceLocation RParenLoc) {
return getSema().BuildBuiltinOffsetOf(OperatorLoc, Type, Components,
- NumComponents, RParenLoc);
+ RParenLoc);
}
/// \brief Build a new sizeof, alignof or vec_step expression with a
@@ -1857,6 +2003,18 @@ public:
RBracketLoc);
}
+ /// \brief Build a new array section expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildOMPArraySectionExpr(Expr *Base, SourceLocation LBracketLoc,
+ Expr *LowerBound,
+ SourceLocation ColonLoc, Expr *Length,
+ SourceLocation RBracketLoc) {
+ return getSema().ActOnOMPArraySectionExpr(Base, LBracketLoc, LowerBound,
+ ColonLoc, Length, RBracketLoc);
+ }
+
/// \brief Build a new call expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -1921,7 +2079,8 @@ public:
return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow,
SS, TemplateKWLoc,
FirstQualifierInScope,
- R, ExplicitTemplateArgs);
+ R, ExplicitTemplateArgs,
+ /*S*/nullptr);
}
/// \brief Build a new binary operator expression.
@@ -1987,7 +2146,8 @@ public:
SS, SourceLocation(),
/*FirstQualifierInScope*/ nullptr,
NameInfo,
- /* TemplateArgs */ nullptr);
+ /* TemplateArgs */ nullptr,
+ /*S*/ nullptr);
}
/// \brief Build a new initializer list expression.
@@ -2435,7 +2595,7 @@ public:
TemplateArgs);
return getSema().BuildQualifiedDeclarationNameExpr(
- SS, NameInfo, IsAddressOfOperand, RecoveryTSI);
+ SS, NameInfo, IsAddressOfOperand, /*S*/nullptr, RecoveryTSI);
}
/// \brief Build a new template-id expression.
@@ -2529,7 +2689,7 @@ public:
SS, TemplateKWLoc,
FirstQualifierInScope,
MemberNameInfo,
- TemplateArgs);
+ TemplateArgs, /*S*/nullptr);
}
/// \brief Build a new member reference expression.
@@ -2551,7 +2711,7 @@ public:
OperatorLoc, IsArrow,
SS, TemplateKWLoc,
FirstQualifierInScope,
- R, TemplateArgs);
+ R, TemplateArgs, /*S*/nullptr);
}
/// \brief Build a new noexcept expression.
@@ -2563,18 +2723,14 @@ public:
}
/// \brief Build a new expression to compute the length of a parameter pack.
- ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack,
+ ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc,
+ NamedDecl *Pack,
SourceLocation PackLoc,
SourceLocation RParenLoc,
- Optional<unsigned> Length) {
- if (Length)
- return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(),
- OperatorLoc, Pack, PackLoc,
- RParenLoc, *Length);
-
- return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(),
- OperatorLoc, Pack, PackLoc,
- RParenLoc);
+ Optional<unsigned> Length,
+ ArrayRef<TemplateArgument> PartialArgs) {
+ return SizeOfPackExpr::Create(SemaRef.Context, OperatorLoc, Pack, PackLoc,
+ RParenLoc, Length, PartialArgs);
}
/// \brief Build a new Objective-C boxed expression.
@@ -2608,9 +2764,8 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildObjCDictionaryLiteral(SourceRange Range,
- ObjCDictionaryElement *Elements,
- unsigned NumElements) {
- return getSema().BuildObjCDictionaryLiteral(Range, Elements, NumElements);
+ MutableArrayRef<ObjCDictionaryElement> Elements) {
+ return getSema().BuildObjCDictionaryLiteral(Range, Elements);
}
/// \brief Build a new Objective-C \@encode expression.
@@ -2657,20 +2812,18 @@ public:
ExprResult RebuildObjCMessageExpr(SourceLocation SuperLoc,
Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
+ QualType SuperType,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
MultiExprArg Args,
SourceLocation RBracLoc) {
- ObjCInterfaceDecl *Class = Method->getClassInterface();
- QualType ReceiverTy = SemaRef.Context.getObjCInterfaceType(Class);
-
return Method->isInstanceMethod() ? SemaRef.BuildInstanceMessage(nullptr,
- ReceiverTy,
+ SuperType,
SuperLoc,
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args)
: SemaRef.BuildClassMessage(nullptr,
- ReceiverTy,
+ SuperType,
SuperLoc,
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args);
@@ -2693,7 +2846,8 @@ public:
SS, SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
NameInfo,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
/// \brief Build a new Objective-C property reference expression.
@@ -2711,7 +2865,8 @@ public:
SS, SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
NameInfo,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
/// \brief Build a new Objective-C property reference expression.
@@ -2743,7 +2898,8 @@ public:
SS, SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
NameInfo,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
/// \brief Build a new shuffle vector expression.
@@ -3043,7 +3199,7 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
}
template<typename Derived>
-bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
+bool TreeTransform<Derived>::TransformExprs(Expr *const *Inputs,
unsigned NumInputs,
bool IsCall,
SmallVectorImpl<Expr *> &Outputs,
@@ -3458,7 +3614,7 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
template<typename Derived>
bool TreeTransform<Derived>::TransformTemplateArgument(
const TemplateArgumentLoc &Input,
- TemplateArgumentLoc &Output) {
+ TemplateArgumentLoc &Output, bool Uneval) {
const TemplateArgument &Arg = Input.getArgument();
switch (Arg.getKind()) {
case TemplateArgument::Null:
@@ -3506,8 +3662,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
case TemplateArgument::Expression: {
// Template argument expressions are constant expressions.
- EnterExpressionEvaluationContext Unevaluated(getSema(),
- Sema::ConstantEvaluated);
+ EnterExpressionEvaluationContext Unevaluated(
+ getSema(), Uneval ? Sema::Unevaluated : Sema::ConstantEvaluated);
Expr *InputExpr = Input.getSourceExpression();
if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
@@ -3585,9 +3741,9 @@ public:
template<typename Derived>
template<typename InputIterator>
-bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
- InputIterator Last,
- TemplateArgumentListInfo &Outputs) {
+bool TreeTransform<Derived>::TransformTemplateArguments(
+ InputIterator First, InputIterator Last, TemplateArgumentListInfo &Outputs,
+ bool Uneval) {
for (; First != Last; ++First) {
TemplateArgumentLoc Out;
TemplateArgumentLoc In = *First;
@@ -3605,7 +3761,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
In.getArgument().pack_begin()),
PackLocIterator(*this,
In.getArgument().pack_end()),
- Outputs))
+ Outputs, Uneval))
return true;
continue;
@@ -3643,7 +3799,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
// expansion.
TemplateArgumentLoc OutPattern;
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
- if (getDerived().TransformTemplateArgument(Pattern, OutPattern))
+ if (getDerived().TransformTemplateArgument(Pattern, OutPattern, Uneval))
return true;
Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis,
@@ -3660,7 +3816,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
- if (getDerived().TransformTemplateArgument(Pattern, Out))
+ if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval))
return true;
if (Out.getArgument().containsUnexpandedParameterPack()) {
@@ -3678,7 +3834,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
if (RetainExpansion) {
ForgetPartiallySubstitutedPackRAII Forget(getDerived());
- if (getDerived().TransformTemplateArgument(Pattern, Out))
+ if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval))
return true;
Out = getDerived().RebuildPackExpansion(Out, Ellipsis,
@@ -3693,7 +3849,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
}
// The simple case:
- if (getDerived().TransformTemplateArgument(In, Out))
+ if (getDerived().TransformTemplateArgument(In, Out, Uneval))
return true;
Outputs.addArgument(Out);
@@ -3810,7 +3966,7 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
Qs.removeObjCLifetime();
Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
Qs);
- Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(),
+ Result = SemaRef.Context.getAutoType(Deduced, AutoTy->getKeyword(),
AutoTy->isDependentType());
TLB.TypeWasModifiedSafely(Result);
} else {
@@ -4700,9 +4856,7 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType(
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType() ||
- T->getNumParams() != ParamTypes.size() ||
- !std::equal(T->param_type_begin(), T->param_type_end(),
- ParamTypes.begin()) || EPIChanged) {
+ T->getParamTypes() != llvm::makeArrayRef(ParamTypes) || EPIChanged) {
Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, EPI);
if (Result.isNull())
return QualType();
@@ -5015,7 +5169,7 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced ||
T->isDependentType()) {
- Result = getDerived().RebuildAutoType(NewDeduced, T->isDecltypeAuto());
+ Result = getDerived().RebuildAutoType(NewDeduced, T->getKeyword());
if (Result.isNull())
return QualType();
}
@@ -6119,6 +6273,11 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
if (Init.isInvalid())
return StmtError();
+ // In OpenMP loop region loop control variable must be captured and be
+ // private. Perform analysis of first part (if any).
+ if (getSema().getLangOpts().OpenMP && Init.isUsable())
+ getSema().ActOnOpenMPLoopInitialization(S->getForLoc(), Init.get());
+
// Transform the condition
ExprResult Cond;
VarDecl *ConditionVar = nullptr;
@@ -6351,6 +6510,56 @@ TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) {
TransformedExprs, S->getEndLoc());
}
+// C++ Coroutines TS
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
+ // The coroutine body should be re-formed by the caller if necessary.
+ return getDerived().TransformStmt(S->getBody());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCoreturnStmt(CoreturnStmt *S) {
+ ExprResult Result = getDerived().TransformInitializer(S->getOperand(),
+ /*NotCopyInit*/false);
+ if (Result.isInvalid())
+ return StmtError();
+
+ // Always rebuild; we don't know if this needs to be injected into a new
+ // context or if the promise type has changed.
+ return getDerived().RebuildCoreturnStmt(S->getKeywordLoc(), Result.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCoawaitExpr(CoawaitExpr *E) {
+ ExprResult Result = getDerived().TransformInitializer(E->getOperand(),
+ /*NotCopyInit*/false);
+ if (Result.isInvalid())
+ return ExprError();
+
+ // Always rebuild; we don't know if this needs to be injected into a new
+ // context or if the promise type has changed.
+ return getDerived().RebuildCoawaitExpr(E->getKeywordLoc(), Result.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCoyieldExpr(CoyieldExpr *E) {
+ ExprResult Result = getDerived().TransformInitializer(E->getOperand(),
+ /*NotCopyInit*/false);
+ if (Result.isInvalid())
+ return ExprError();
+
+ // Always rebuild; we don't know if this needs to be injected into a new
+ // context or if the promise type has changed.
+ return getDerived().RebuildCoyieldExpr(E->getKeywordLoc(), Result.get());
+}
+
+// Objective-C Statements.
+
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
@@ -6640,6 +6849,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
Inc.get() != S->getInc() ||
LoopVar.get() != S->getLoopVarStmt()) {
NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
+ S->getCoawaitLoc(),
S->getColonLoc(), Range.get(),
BeginEnd.get(), Cond.get(),
Inc.get(), LoopVar.get(),
@@ -6656,6 +6866,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
// it now so we have a new statement to attach the body to.
if (Body.get() != S->getBody() && NewStmt.get() == S) {
NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
+ S->getCoawaitLoc(),
S->getColonLoc(), Range.get(),
BeginEnd.get(), Cond.get(),
Inc.get(), LoopVar.get(),
@@ -6766,6 +6977,25 @@ TreeTransform<Derived>::TransformMSPropertyRefExpr(MSPropertyRefExpr *E) {
}
template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformMSPropertySubscriptExpr(
+ MSPropertySubscriptExpr *E) {
+ auto BaseRes = getDerived().TransformExpr(E->getBase());
+ if (BaseRes.isInvalid())
+ return ExprError();
+ auto IdxRes = getDerived().TransformExpr(E->getIdx());
+ if (IdxRes.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ BaseRes.get() == E->getBase() &&
+ IdxRes.get() == E->getIdx())
+ return E;
+
+ return getDerived().RebuildArraySubscriptExpr(
+ BaseRes.get(), SourceLocation(), IdxRes.get(), E->getRBracketLoc());
+}
+
+template <typename Derived>
StmtResult TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
StmtResult TryBlock = getDerived().TransformCompoundStmt(S->getTryBlock());
if (TryBlock.isInvalid())
@@ -6844,10 +7074,7 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
}
}
StmtResult AssociatedStmt;
- if (D->hasAssociatedStmt()) {
- if (!D->getAssociatedStmt()) {
- return StmtError();
- }
+ if (D->hasAssociatedStmt() && D->getAssociatedStmt()) {
getDerived().getSema().ActOnOpenMPRegionStart(D->getDirectiveKind(),
/*CurScope=*/nullptr);
StmtResult Body;
@@ -7115,6 +7342,17 @@ TreeTransform<Derived>::TransformOMPTargetDirective(OMPTargetDirective *D) {
}
template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTargetDataDirective(
+ OMPTargetDataDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_target_data, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPTeamsDirective(OMPTeamsDirective *D) {
DeclarationNameInfo DirName;
@@ -7147,6 +7385,39 @@ TreeTransform<Derived>::TransformOMPCancelDirective(OMPCancelDirective *D) {
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTaskLoopDirective(OMPTaskLoopDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTaskLoopSimdDirective(
+ OMPTaskLoopSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop_simd, DirName,
+ nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPDistributeDirective(
+ OMPDistributeDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_distribute, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
@@ -7155,8 +7426,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
ExprResult Cond = getDerived().TransformExpr(C->getCondition());
if (Cond.isInvalid())
return nullptr;
- return getDerived().RebuildOMPIfClause(Cond.get(), C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPIfClause(
+ C->getNameModifier(), Cond.get(), C->getLocStart(), C->getLParenLoc(),
+ C->getNameModifierLoc(), C->getColonLoc(), C->getLocEnd());
}
template <typename Derived>
@@ -7190,10 +7462,20 @@ TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
template <typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPSimdlenClause(OMPSimdlenClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getSimdlen());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPSimdlenClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPCollapseClause(OMPCollapseClause *C) {
ExprResult E = getDerived().TransformExpr(C->getNumForLoops());
if (E.isInvalid())
- return 0;
+ return nullptr;
return getDerived().RebuildOMPCollapseClause(
E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
@@ -7221,15 +7503,23 @@ TreeTransform<Derived>::TransformOMPScheduleClause(OMPScheduleClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPScheduleClause(
+ C->getFirstScheduleModifier(), C->getSecondScheduleModifier(),
C->getScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
+ C->getFirstScheduleModifierLoc(), C->getSecondScheduleModifierLoc(),
C->getScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPOrderedClause(OMPOrderedClause *C) {
- // No need to rebuild this clause, no template-dependent parameters.
- return C;
+ ExprResult E;
+ if (auto *Num = C->getNumForLoops()) {
+ E = getDerived().TransformExpr(Num);
+ if (E.isInvalid())
+ return nullptr;
+ }
+ return getDerived().RebuildOMPOrderedClause(C->getLocStart(), C->getLocEnd(),
+ C->getLParenLoc(), E.get());
}
template <typename Derived>
@@ -7288,6 +7578,26 @@ TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
template <typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPThreadsClause(OMPThreadsClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPSIMDClause(OMPSIMDClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNogroupClause(OMPNogroupClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
@@ -7385,9 +7695,9 @@ TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
ExprResult Step = getDerived().TransformExpr(C->getStep());
if (Step.isInvalid())
return nullptr;
- return getDerived().RebuildOMPLinearClause(Vars, Step.get(), C->getLocStart(),
- C->getLParenLoc(),
- C->getColonLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPLinearClause(
+ Vars, Step.get(), C->getLocStart(), C->getLParenLoc(), C->getModifier(),
+ C->getModifierLoc(), C->getColonLoc(), C->getLocEnd());
}
template <typename Derived>
@@ -7469,6 +7779,91 @@ TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPDeviceClause(OMPDeviceClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getDevice());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPDeviceClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPMapClause(
+ C->getMapTypeModifier(), C->getMapType(), C->getMapLoc(),
+ C->getColonLoc(), Vars, C->getLocStart(), C->getLParenLoc(),
+ C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNumTeamsClause(OMPNumTeamsClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getNumTeams());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPNumTeamsClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPThreadLimitClause(OMPThreadLimitClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getThreadLimit());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPThreadLimitClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPPriorityClause(OMPPriorityClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getPriority());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPPriorityClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPGrainsizeClause(OMPGrainsizeClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getGrainsize());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPGrainsizeClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNumTasksClause(OMPNumTasksClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getNumTasks());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPNumTasksClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPHintClause(OMPHintClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getHint());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPHintClause(E.get(), C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
@@ -7668,16 +8063,15 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
// template code that we don't care.
bool ExprChanged = false;
typedef Sema::OffsetOfComponent Component;
- typedef OffsetOfExpr::OffsetOfNode Node;
SmallVector<Component, 4> Components;
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
- const Node &ON = E->getComponent(I);
+ const OffsetOfNode &ON = E->getComponent(I);
Component Comp;
Comp.isBrackets = true;
Comp.LocStart = ON.getSourceRange().getBegin();
Comp.LocEnd = ON.getSourceRange().getEnd();
switch (ON.getKind()) {
- case Node::Array: {
+ case OffsetOfNode::Array: {
Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex());
ExprResult Index = getDerived().TransformExpr(FromIndex);
if (Index.isInvalid())
@@ -7689,8 +8083,8 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
break;
}
- case Node::Field:
- case Node::Identifier:
+ case OffsetOfNode::Field:
+ case OffsetOfNode::Identifier:
Comp.isBrackets = false;
Comp.U.IdentInfo = ON.getFieldName();
if (!Comp.U.IdentInfo)
@@ -7698,7 +8092,7 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
break;
- case Node::Base:
+ case OffsetOfNode::Base:
// Will be recomputed during the rebuild.
continue;
}
@@ -7714,14 +8108,13 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
// Build a new offsetof expression.
return getDerived().RebuildOffsetOfExpr(E->getOperatorLoc(), Type,
- Components.data(), Components.size(),
- E->getRParenLoc());
+ Components, E->getRParenLoc());
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
- assert(getDerived().AlreadyTransformed(E->getType()) &&
+ assert((!E->getSourceExpr() || getDerived().AlreadyTransformed(E->getType())) &&
"opaque value expression requires transformation");
return E;
}
@@ -7829,6 +8222,36 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
E->getRBracketLoc());
}
+template <typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformOMPArraySectionExpr(OMPArraySectionExpr *E) {
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ ExprResult LowerBound;
+ if (E->getLowerBound()) {
+ LowerBound = getDerived().TransformExpr(E->getLowerBound());
+ if (LowerBound.isInvalid())
+ return ExprError();
+ }
+
+ ExprResult Length;
+ if (E->getLength()) {
+ Length = getDerived().TransformExpr(E->getLength());
+ if (Length.isInvalid())
+ return ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() &&
+ LowerBound.get() == E->getLowerBound() && Length.get() == E->getLength())
+ return E;
+
+ return getDerived().RebuildOMPArraySectionExpr(
+ Base.get(), E->getBase()->getLocEnd(), LowerBound.get(), E->getColonLoc(),
+ Length.get(), E->getRBracketLoc());
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
@@ -8995,9 +9418,20 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc();
// If we have neither explicit template arguments, nor the template keyword,
- // it's a normal declaration name.
- if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid())
+ // it's a normal declaration name or member reference.
+ if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) {
+ NamedDecl *D = R.getAsSingle<NamedDecl>();
+ // In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an
+ // instance member. In other contexts, BuildPossibleImplicitMemberExpr will
+ // give a good diagnostic.
+ if (D && D->isCXXInstanceMember()) {
+ return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R,
+ /*TemplateArgs=*/nullptr,
+ /*Scope=*/nullptr);
+ }
+
return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
+ }
// If we have template arguments, rebuild them, then rebuild the
// templateid expression.
@@ -9404,9 +9838,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
VarDecl *OldVD = C->getCapturedVar();
QualType NewInitCaptureType =
- getSema().performLambdaInitCaptureInitialization(C->getLocation(),
- OldVD->getType()->isReferenceType(), OldVD->getIdentifier(),
- NewExprInit);
+ getSema().buildLambdaInitCaptureInitialization(
+ C->getLocation(), OldVD->getType()->isReferenceType(),
+ OldVD->getIdentifier(),
+ C->getCapturedVar()->getInitStyle() != VarDecl::CInit, NewExprInit);
NewExprInitResult = NewExprInit;
InitCaptureExprsAndTypes[C - E->capture_begin()] =
std::make_pair(NewExprInitResult, NewInitCaptureType);
@@ -9513,8 +9948,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
}
VarDecl *OldVD = C->getCapturedVar();
VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl(
- OldVD->getLocation(), InitExprTypePair.second,
- OldVD->getIdentifier(), Init.get());
+ OldVD->getLocation(), InitExprTypePair.second, OldVD->getIdentifier(),
+ OldVD->getInitStyle(), Init.get());
if (!NewVD)
Invalid = true;
else {
@@ -9886,36 +10321,86 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
if (!E->isValueDependent())
return E;
- // Note: None of the implementations of TryExpandParameterPacks can ever
- // produce a diagnostic when given only a single unexpanded parameter pack,
- // so
- UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
- bool ShouldExpand = false;
- bool RetainExpansion = false;
- Optional<unsigned> NumExpansions;
- if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(),
- Unexpanded,
- ShouldExpand, RetainExpansion,
- NumExpansions))
- return ExprError();
+ EnterExpressionEvaluationContext Unevaluated(getSema(), Sema::Unevaluated);
- if (RetainExpansion)
- return E;
+ ArrayRef<TemplateArgument> PackArgs;
+ TemplateArgument ArgStorage;
- NamedDecl *Pack = E->getPack();
- if (!ShouldExpand) {
- Pack = cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getPackLoc(),
- Pack));
+ // Find the argument list to transform.
+ if (E->isPartiallySubstituted()) {
+ PackArgs = E->getPartialArguments();
+ } else if (E->isValueDependent()) {
+ UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
+ bool ShouldExpand = false;
+ bool RetainExpansion = false;
+ Optional<unsigned> NumExpansions;
+ if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(),
+ Unexpanded,
+ ShouldExpand, RetainExpansion,
+ NumExpansions))
+ return ExprError();
+
+ // If we need to expand the pack, build a template argument from it and
+ // expand that.
+ if (ShouldExpand) {
+ auto *Pack = E->getPack();
+ if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Pack)) {
+ ArgStorage = getSema().Context.getPackExpansionType(
+ getSema().Context.getTypeDeclType(TTPD), None);
+ } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Pack)) {
+ ArgStorage = TemplateArgument(TemplateName(TTPD), None);
+ } else {
+ auto *VD = cast<ValueDecl>(Pack);
+ ExprResult DRE = getSema().BuildDeclRefExpr(VD, VD->getType(),
+ VK_RValue, E->getPackLoc());
+ if (DRE.isInvalid())
+ return ExprError();
+ ArgStorage = new (getSema().Context) PackExpansionExpr(
+ getSema().Context.DependentTy, DRE.get(), E->getPackLoc(), None);
+ }
+ PackArgs = ArgStorage;
+ }
+ }
+
+ // If we're not expanding the pack, just transform the decl.
+ if (!PackArgs.size()) {
+ auto *Pack = cast_or_null<NamedDecl>(
+ getDerived().TransformDecl(E->getPackLoc(), E->getPack()));
if (!Pack)
return ExprError();
+ return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack,
+ E->getPackLoc(),
+ E->getRParenLoc(), None, None);
}
+ TemplateArgumentListInfo TransformedPackArgs(E->getPackLoc(),
+ E->getPackLoc());
+ {
+ TemporaryBase Rebase(*this, E->getPackLoc(), getBaseEntity());
+ typedef TemplateArgumentLocInventIterator<
+ Derived, const TemplateArgument*> PackLocIterator;
+ if (TransformTemplateArguments(PackLocIterator(*this, PackArgs.begin()),
+ PackLocIterator(*this, PackArgs.end()),
+ TransformedPackArgs, /*Uneval*/true))
+ return ExprError();
+ }
- // We now know the length of the parameter pack, so build a new expression
- // that stores that length.
- return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack,
+ SmallVector<TemplateArgument, 8> Args;
+ bool PartialSubstitution = false;
+ for (auto &Loc : TransformedPackArgs.arguments()) {
+ Args.push_back(Loc.getArgument());
+ if (Loc.getArgument().isPackExpansion())
+ PartialSubstitution = true;
+ }
+
+ if (PartialSubstitution)
+ return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(),
+ E->getPackLoc(),
+ E->getRParenLoc(), None, Args);
+
+ return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(),
E->getPackLoc(), E->getRParenLoc(),
- NumExpansions);
+ Args.size(), None);
}
template<typename Derived>
@@ -10242,8 +10727,7 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
return SemaRef.MaybeBindToTemporary(E);
return getDerived().RebuildObjCDictionaryLiteral(E->getSourceRange(),
- Elements.data(),
- Elements.size());
+ Elements);
}
template<typename Derived>
@@ -10337,6 +10821,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
return getDerived().RebuildObjCMessageExpr(E->getSuperLoc(),
E->getSelector(),
SelLocs,
+ E->getReceiverType(),
E->getMethodDecl(),
E->getLeftLoc(),
Args,
@@ -11075,7 +11560,8 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
SS, TemplateKWLoc,
/*FIXME: FirstQualifier*/ nullptr,
NameInfo,
- /*TemplateArgs*/ nullptr);
+ /*TemplateArgs*/ nullptr,
+ /*S*/nullptr);
}
template<typename Derived>
@@ -11114,4 +11600,4 @@ TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) {
} // end namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_SEMA_TREETRANSFORM_H