aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp144
-rw-r--r--lib/Sema/AttributeList.cpp13
-rw-r--r--lib/Sema/CMakeLists.txt2
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp61
-rw-r--r--lib/Sema/DeclSpec.cpp84
-rw-r--r--lib/Sema/IdentifierResolver.cpp14
-rw-r--r--lib/Sema/JumpDiagnostics.cpp14
-rw-r--r--lib/Sema/MultiplexExternalSemaSource.cpp28
-rw-r--r--lib/Sema/Sema.cpp272
-rw-r--r--lib/Sema/SemaAccess.cpp271
-rw-r--r--lib/Sema/SemaAttr.cpp5
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp45
-rw-r--r--lib/Sema/SemaCast.cpp132
-rw-r--r--lib/Sema/SemaChecking.cpp922
-rw-r--r--lib/Sema/SemaCodeComplete.cpp540
-rw-r--r--lib/Sema/SemaDecl.cpp2272
-rw-r--r--lib/Sema/SemaDeclAttr.cpp1240
-rw-r--r--lib/Sema/SemaDeclCXX.cpp2314
-rw-r--r--lib/Sema/SemaDeclObjC.cpp359
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp116
-rw-r--r--lib/Sema/SemaExpr.cpp976
-rw-r--r--lib/Sema/SemaExprCXX.cpp395
-rw-r--r--lib/Sema/SemaExprMember.cpp110
-rw-r--r--lib/Sema/SemaExprObjC.cpp340
-rw-r--r--lib/Sema/SemaFixItUtils.cpp4
-rw-r--r--lib/Sema/SemaInit.cpp439
-rw-r--r--lib/Sema/SemaLambda.cpp294
-rw-r--r--lib/Sema/SemaLookup.cpp233
-rw-r--r--lib/Sema/SemaObjCProperty.cpp468
-rw-r--r--lib/Sema/SemaOpenMP.cpp181
-rw-r--r--lib/Sema/SemaOverload.cpp448
-rw-r--r--lib/Sema/SemaPseudoObject.cpp27
-rw-r--r--lib/Sema/SemaStmt.cpp201
-rw-r--r--lib/Sema/SemaStmtAsm.cpp99
-rw-r--r--lib/Sema/SemaStmtAttr.cpp4
-rw-r--r--lib/Sema/SemaTemplate.cpp208
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp104
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp120
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp334
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp57
-rw-r--r--lib/Sema/SemaType.cpp860
-rw-r--r--lib/Sema/TargetAttributesSema.cpp76
-rw-r--r--lib/Sema/TreeTransform.h316
-rw-r--r--lib/Sema/TypeLocBuilder.h8
44 files changed, 9996 insertions, 5154 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 801a1b1e0264..00d3c47525d3 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -14,42 +14,43 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/AnalysisBasedWarnings.h"
-#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtObjC.h"
-#include "clang/AST/StmtCXX.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/ParentMap.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Analysis/AnalysisContext.h"
-#include "clang/Analysis/CFG.h"
-#include "clang/Analysis/Analyses/ReachableCode.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/Analysis/Analyses/ReachableCode.h"
#include "clang/Analysis/Analyses/ThreadSafety.h"
-#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Analyses/UninitializedValues.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#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"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include <algorithm>
+#include <deque>
#include <iterator>
#include <vector>
-#include <deque>
using namespace clang;
@@ -157,7 +158,7 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
for ( ; ri != re ; ++ri)
- if (isa<CFGStmt>(*ri))
+ if (ri->getAs<CFGStmt>())
break;
// No more CFGElements in the block?
@@ -171,7 +172,7 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
continue;
}
- CFGStmt CS = cast<CFGStmt>(*ri);
+ CFGStmt CS = ri->castAs<CFGStmt>();
const Stmt *S = CS.getStmt();
if (isa<ReturnStmt>(S)) {
HasLiveReturn = true;
@@ -329,8 +330,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
ReturnsVoid = FD->getResultType()->isVoidType();
- HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
- FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
+ HasNoReturn = FD->isNoReturn();
}
else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
ReturnsVoid = MD->getResultType()->isVoidType();
@@ -505,7 +505,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
StringRef Str;
SourceRange Range;
- // FixIts to suppress the diagnosic by removing the dead condition.
+ // FixIts to suppress the diagnostic by removing the dead condition.
// For all binary terminators, branch 0 is taken if the condition is true,
// and branch 1 is taken if the condition is false.
int RemoveDiagKind = -1;
@@ -703,7 +703,38 @@ namespace {
return FallthroughStmts;
}
+ void fillReachableBlocks(CFG *Cfg) {
+ assert(ReachableBlocks.empty() && "ReachableBlocks already filled");
+ std::deque<const CFGBlock *> BlockQueue;
+
+ ReachableBlocks.insert(&Cfg->getEntry());
+ BlockQueue.push_back(&Cfg->getEntry());
+ // Mark all case blocks reachable to avoid problems with switching on
+ // constants, covered enums, etc.
+ // These blocks can contain fall-through annotations, and we don't want to
+ // issue a warn_fallthrough_attr_unreachable for them.
+ for (CFG::iterator I = Cfg->begin(), E = Cfg->end(); I != E; ++I) {
+ const CFGBlock *B = *I;
+ const Stmt *L = B->getLabel();
+ if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B))
+ BlockQueue.push_back(B);
+ }
+
+ while (!BlockQueue.empty()) {
+ const CFGBlock *P = BlockQueue.front();
+ BlockQueue.pop_front();
+ for (CFGBlock::const_succ_iterator I = P->succ_begin(),
+ E = P->succ_end();
+ I != E; ++I) {
+ if (*I && ReachableBlocks.insert(*I))
+ BlockQueue.push_back(*I);
+ }
+ }
+ }
+
bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) {
+ assert(!ReachableBlocks.empty() && "ReachableBlocks empty");
+
int UnannotatedCnt = 0;
AnnotatedCnt = 0;
@@ -723,16 +754,21 @@ namespace {
if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end())
continue; // Previous case label has no statements, good.
- if (P->pred_begin() == P->pred_end()) { // The block is unreachable.
- // This only catches trivially unreachable blocks.
- for (CFGBlock::const_iterator ElIt = P->begin(), ElEnd = P->end();
- ElIt != ElEnd; ++ElIt) {
- if (const CFGStmt *CS = ElIt->getAs<CFGStmt>()){
+ const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel());
+ if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end())
+ continue; // Case label is preceded with a normal label, good.
+
+ if (!ReachableBlocks.count(P)) {
+ for (CFGBlock::const_reverse_iterator ElemIt = P->rbegin(),
+ ElemEnd = P->rend();
+ ElemIt != ElemEnd; ++ElemIt) {
+ if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) {
if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
S.Diag(AS->getLocStart(),
diag::warn_fallthrough_attr_unreachable);
markFallthroughVisited(AS);
++AnnotatedCnt;
+ break;
}
// Don't care about other unreachable statements.
}
@@ -781,6 +817,10 @@ namespace {
return true;
}
+ // We don't want to traverse local type declarations. We analyze their
+ // methods separately.
+ bool TraverseDecl(Decl *D) { return true; }
+
private:
static const AttributedStmt *asFallThroughAttr(const Stmt *S) {
@@ -797,7 +837,7 @@ namespace {
for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(),
ElemEnd = B.rend();
ElemIt != ElemEnd; ++ElemIt) {
- if (const CFGStmt *CS = ElemIt->getAs<CFGStmt>())
+ if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>())
return CS->getStmt();
}
// Workaround to detect a statement thrown out by CFGBuilder:
@@ -813,6 +853,7 @@ namespace {
bool FoundSwitchStatements;
AttrStmts FallthroughStmts;
Sema &S;
+ llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
};
}
@@ -827,7 +868,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
//
// NOTE: This an intermediate solution. There are on-going discussions on
// how to properly support this warning outside of C++11 with an annotation.
- if (!AC.getASTContext().getLangOpts().CPlusPlus0x)
+ if (!AC.getASTContext().getLangOpts().CPlusPlus11)
return;
FallthroughMapper FM(S);
@@ -844,16 +885,18 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
if (!Cfg)
return;
- int AnnotatedCnt;
+ FM.fillReachableBlocks(Cfg);
for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) {
- const CFGBlock &B = **I;
- const Stmt *Label = B.getLabel();
+ const CFGBlock *B = *I;
+ const Stmt *Label = B->getLabel();
if (!Label || !isa<SwitchCase>(Label))
continue;
- if (!FM.checkFallThroughIntoBlock(B, AnnotatedCnt))
+ int AnnotatedCnt;
+
+ if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt))
continue;
S.Diag(Label->getLocStart(),
@@ -864,9 +907,14 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
SourceLocation L = Label->getLocStart();
if (L.isMacroID())
continue;
- if (S.getLangOpts().CPlusPlus0x) {
- const Stmt *Term = B.getTerminator();
- if (!(B.empty() && Term && isa<BreakStmt>(Term))) {
+ if (S.getLangOpts().CPlusPlus11) {
+ const Stmt *Term = B->getTerminator();
+ // Skip empty cases.
+ while (B->empty() && !Term && B->succ_size() == 1) {
+ B = *B->succ_begin();
+ Term = B->getTerminator();
+ }
+ if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
Preprocessor &PP = S.getPreprocessor();
TokenValue Tokens[] = {
tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"),
@@ -1106,7 +1154,11 @@ struct SLocSort {
class UninitValsDiagReporter : public UninitVariablesHandler {
Sema &S;
typedef SmallVector<UninitUse, 2> UsesVec;
- typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap;
+ typedef std::pair<UsesVec*, bool> MappedType;
+ // Prefer using MapVector to DenseMap, so that iteration order will be
+ // 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;
public:
@@ -1115,11 +1167,11 @@ public:
flushDiagnostics();
}
- std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) {
+ MappedType &getUses(const VarDecl *vd) {
if (!uses)
uses = new UsesMap();
- UsesMap::mapped_type &V = (*uses)[vd];
+ MappedType &V = (*uses)[vd];
UsesVec *&vec = V.first;
if (!vec)
vec = new UsesVec();
@@ -1138,12 +1190,10 @@ public:
void flushDiagnostics() {
if (!uses)
return;
-
- // FIXME: This iteration order, and thus the resulting diagnostic order,
- // is nondeterministic.
+
for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
const VarDecl *vd = i->first;
- const UsesMap::mapped_type &V = i->second;
+ const MappedType &V = i->second;
UsesVec *vec = V.first;
bool hasSelfInit = V.second;
@@ -1198,7 +1248,7 @@ private:
//===----------------------------------------------------------------------===//
namespace clang {
namespace thread_safety {
-typedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
+typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
typedef std::list<DelayedDiag> DiagList;
@@ -1423,7 +1473,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
if (cast<DeclContext>(D)->isDependentContext())
return;
- if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) {
+ if (Diags.hasUncompilableErrorOccurred() || Diags.hasFatalErrorOccurred()) {
// Flush out any possibly unreachable diagnostics.
flushDiagnostics(S, fscope);
return;
@@ -1544,6 +1594,10 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
SourceLocation FL = AC.getDecl()->getLocation();
SourceLocation FEL = AC.getDecl()->getLocEnd();
thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL);
+ if (Diags.getDiagnosticLevel(diag::warn_thread_safety_beta,D->getLocStart())
+ != DiagnosticsEngine::Ignored)
+ Reporter.setIssueBetaWarnings(true);
+
thread_safety::runThreadSafetyAnalysis(AC, Reporter);
Reporter.emitDiagnostics();
}
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp
index 7c79879d976c..e227d4e840b3 100644
--- a/lib/Sema/AttributeList.cpp
+++ b/lib/Sema/AttributeList.cpp
@@ -15,8 +15,8 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace clang;
size_t AttributeList::allocated_size() const {
@@ -125,3 +125,14 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
return ::getAttrKind(Buf);
}
+
+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() : "";
+
+#include "clang/Sema/AttrSpellingListIndex.inc"
+
+}
+
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 7cfe3ae8462c..e92f76713422 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -38,6 +38,7 @@ add_clang_library(clangSema
SemaLambda.cpp
SemaLookup.cpp
SemaObjCProperty.cpp
+ SemaOpenMP.cpp
SemaOverload.cpp
SemaPseudoObject.cpp
SemaStmt.cpp
@@ -58,6 +59,7 @@ add_dependencies(clangSema
ClangAttrList
ClangAttrParsedAttrList
ClangAttrParsedAttrKinds
+ ClangAttrSpellingListIndex
ClangAttrTemplateInstantiate
ClangCommentNodes
ClangDeclNodes
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 0a236018bdfd..19be1cb42fe7 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/CodeCompleteConsumer.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/Sema.h"
+#include "clang-c/Index.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang-c/Index.h"
-#include "llvm/ADT/SmallString.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Sema.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -267,8 +267,8 @@ const char *CodeCompletionAllocator::CopyString(Twine String) {
return CopyString(String.toStringRef(Data));
}
-StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) {
- NamedDecl *ND = dyn_cast<NamedDecl>(DC);
+StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
+ const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
if (!ND)
return StringRef();
@@ -283,9 +283,9 @@ StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) {
return StringRef();
// Find the interesting names.
- llvm::SmallVector<DeclContext *, 2> Contexts;
+ SmallVector<const DeclContext *, 2> Contexts;
while (DC && !DC->isFunctionOrMethod()) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
if (ND->getIdentifier())
Contexts.push_back(DC);
}
@@ -294,7 +294,7 @@ StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) {
}
{
- llvm::SmallString<128> S;
+ SmallString<128> S;
llvm::raw_svector_ostream OS(S);
bool First = true;
for (unsigned I = Contexts.size(); I != 0; --I) {
@@ -304,12 +304,12 @@ StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) {
OS << "::";
}
- DeclContext *CurDC = Contexts[I-1];
- if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
+ const DeclContext *CurDC = Contexts[I-1];
+ if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
CurDC = CatImpl->getCategoryDecl();
- if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
- ObjCInterfaceDecl *Interface = Cat->getClassInterface();
+ if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
+ const ObjCInterfaceDecl *Interface = Cat->getClassInterface();
if (!Interface) {
// Assign an empty StringRef but with non-null data to distinguish
// between empty because we didn't process the DeclContext yet.
@@ -377,7 +377,7 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
Chunks.push_back(Chunk(CK, Text));
}
-void CodeCompletionBuilder::addParentContext(DeclContext *DC) {
+void CodeCompletionBuilder::addParentContext(const DeclContext *DC) {
if (DC->isTranslationUnit()) {
return;
}
@@ -385,7 +385,7 @@ void CodeCompletionBuilder::addParentContext(DeclContext *DC) {
if (DC->isFunctionOrMethod())
return;
- NamedDecl *ND = dyn_cast<NamedDecl>(DC);
+ const NamedDecl *ND = dyn_cast<NamedDecl>(DC);
if (!ND)
return;
@@ -396,33 +396,6 @@ void CodeCompletionBuilder::addBriefComment(StringRef Comment) {
BriefComment = Allocator.CopyString(Comment);
}
-unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
- if (!ND)
- return CCP_Unlikely;
-
- // Context-based decisions.
- DeclContext *DC = ND->getDeclContext()->getRedeclContext();
- if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
- // _cmd is relatively rare
- if (ImplicitParamDecl *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
- if (ImplicitParam->getIdentifier() &&
- ImplicitParam->getIdentifier()->isStr("_cmd"))
- return CCP_ObjC_cmd;
-
- return CCP_LocalDeclaration;
- }
- if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
- return CCP_MemberDeclaration;
-
- // Content-based decisions.
- if (isa<EnumConstantDecl>(ND))
- return CCP_Constant;
- if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
- return CCP_Type;
-
- return CCP_Declaration;
-}
-
//===----------------------------------------------------------------------===//
// Code completion overload candidate implementation
//===----------------------------------------------------------------------===//
@@ -526,7 +499,7 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
}
/// \brief Retrieve the effective availability of the given declaration.
-static AvailabilityResult getDeclAvailability(Decl *D) {
+static AvailabilityResult getDeclAvailability(const Decl *D) {
AvailabilityResult AR = D->getAvailability();
if (isa<EnumConstantDecl>(D))
AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability());
@@ -559,7 +532,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
break;
}
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
if (Function->isDeleted())
Availability = CXAvailability_NotAvailable;
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index b3066eb08013..e1d55dbddccf 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -11,18 +11,18 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/LocInfoType.h"
-#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "clang/Sema/Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.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/Support/ErrorHandling.h"
#include <cstring>
@@ -169,6 +169,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
TypeResult TrailingReturnType) {
+ assert(!(TypeQuals & DeclSpec::TQ_atomic) &&
+ "function cannot have _Atomic qualifier");
+
DeclaratorChunk I;
I.Kind = Function;
I.Loc = LocalRangeBegin;
@@ -280,6 +283,14 @@ bool Declarator::isDeclarationOfFunction() const {
case TST_unspecified:
case TST_void:
case TST_wchar:
+ case TST_image1d_t:
+ case TST_image1d_array_t:
+ case TST_image1d_buffer_t:
+ case TST_image2d_t:
+ case TST_image2d_array_t:
+ case TST_image3d_t:
+ case TST_sampler_t:
+ case TST_event_t:
return false;
case TST_decltype:
@@ -323,7 +334,8 @@ unsigned DeclSpec::getParsedSpecifiers() const {
if (hasTypeSpecifier())
Res |= PQ_TypeSpecifier;
- if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified)
+ if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified ||
+ FS_noreturn_specified)
Res |= PQ_FunctionSpecifier;
return Res;
}
@@ -414,6 +426,14 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
case DeclSpec::TST_underlyingType: return "__underlying_type";
case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
case DeclSpec::TST_atomic: return "_Atomic";
+ case DeclSpec::TST_image1d_t: return "image1d_t";
+ case DeclSpec::TST_image1d_array_t: return "image1d_array_t";
+ case DeclSpec::TST_image1d_buffer_t: return "image1d_buffer_t";
+ case DeclSpec::TST_image2d_t: return "image2d_t";
+ case DeclSpec::TST_image2d_array_t: return "image2d_array_t";
+ case DeclSpec::TST_image3d_t: return "image3d_t";
+ case DeclSpec::TST_sampler_t: return "sampler_t";
+ case DeclSpec::TST_event_t: return "event_t";
case DeclSpec::TST_error: return "(error)";
}
llvm_unreachable("Unknown typespec!");
@@ -425,6 +445,7 @@ const char *DeclSpec::getSpecifierName(TQ T) {
case DeclSpec::TQ_const: return "const";
case DeclSpec::TQ_restrict: return "restrict";
case DeclSpec::TQ_volatile: return "volatile";
+ case DeclSpec::TQ_atomic: return "_Atomic";
}
llvm_unreachable("Unknown typespec!");
}
@@ -693,38 +714,44 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
TypeQualifiers |= T;
switch (T) {
- default: llvm_unreachable("Unknown type qualifier!");
- case TQ_const: TQ_constLoc = Loc; break;
- case TQ_restrict: TQ_restrictLoc = Loc; break;
- case TQ_volatile: TQ_volatileLoc = Loc; break;
+ case TQ_unspecified: break;
+ case TQ_const: TQ_constLoc = Loc; return false;
+ case TQ_restrict: TQ_restrictLoc = Loc; return false;
+ case TQ_volatile: TQ_volatileLoc = Loc; return false;
+ case TQ_atomic: TQ_atomicLoc = Loc; return false;
}
- return false;
+
+ llvm_unreachable("Unknown type qualifier!");
}
-bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID) {
+bool DeclSpec::setFunctionSpecInline(SourceLocation Loc) {
// 'inline inline' is ok.
FS_inline_specified = true;
FS_inlineLoc = Loc;
return false;
}
-bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID) {
+bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc) {
// 'virtual virtual' is ok.
FS_virtual_specified = true;
FS_virtualLoc = Loc;
return false;
}
-bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID) {
+bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc) {
// 'explicit explicit' is ok.
FS_explicit_specified = true;
FS_explicitLoc = Loc;
return false;
}
+bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc) {
+ // '_Noreturn _Noreturn' is ok.
+ FS_noreturn_specified = true;
+ FS_noreturnLoc = Loc;
+ return false;
+}
+
bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID) {
if (Friend_specified) {
@@ -763,9 +790,10 @@ void DeclSpec::setProtocolQualifiers(Decl * const *Protos,
SourceLocation *ProtoLocs,
SourceLocation LAngleLoc) {
if (NP == 0) return;
- ProtocolQualifiers = new Decl*[NP];
+ Decl **ProtoQuals = new Decl*[NP];
+ memcpy(ProtoQuals, Protos, sizeof(Decl*)*NP);
+ ProtocolQualifiers = ProtoQuals;
ProtocolLocs = new SourceLocation[NP];
- memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP);
memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP);
NumProtocolQualifiers = NP;
ProtocolLAngleLoc = LAngleLoc;
@@ -787,15 +815,6 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
}
}
-void DeclSpec::SaveStorageSpecifierAsWritten() {
- if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern)
- // If 'extern' is part of a linkage specification,
- // then it is not a storage class "as written".
- StorageClassSpecAsWritten = SCS_unspecified;
- else
- StorageClassSpecAsWritten = StorageClassSpec;
-}
-
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
@@ -803,7 +822,6 @@ void DeclSpec::SaveStorageSpecifierAsWritten() {
void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
// Before possibly changing their values, save specs as written.
SaveWrittenBuiltinSpecs();
- SaveStorageSpecifierAsWritten();
// Check the type specifier components first.
@@ -913,15 +931,15 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().MicrosoftExt &&
TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
TypeSpecType = TST_auto;
- StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified;
+ StorageClassSpec = SCS_unspecified;
TSTLoc = TSTNameLoc = StorageClassSpecLoc;
StorageClassSpecLoc = SourceLocation();
}
// Diagnose if we've recovered from an ill-formed 'auto' storage class
// specifier in a pre-C++0x dialect of C++.
- if (!PP.getLangOpts().CPlusPlus0x && TypeSpecType == TST_auto)
+ if (!PP.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto)
Diag(D, TSTLoc, diag::ext_auto_type_specifier);
- if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus0x &&
+ if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus11 &&
StorageClassSpec == SCS_auto)
Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
<< FixItHint::CreateRemoval(StorageClassSpecLoc);
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 7d5530442f48..d44c1fb926f5 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -13,12 +13,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/IdentifierResolver.h"
-#include "clang/Sema/Scope.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclObjC.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Scope.h"
using namespace clang;
@@ -108,8 +107,7 @@ IdentifierResolver::~IdentifierResolver() {
/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
-bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
- ASTContext &Context, Scope *S,
+bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
bool ExplicitInstantiationOrSpecialization) const {
Ctx = Ctx->getRedeclContext();
@@ -304,6 +302,14 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
// If the declarations are redeclarations of each other, keep the newest one.
if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) {
+ // If either of these is the most recent declaration, use it.
+ Decl *MostRecent = Existing->getMostRecentDecl();
+ if (Existing == MostRecent)
+ return DMK_Ignore;
+
+ if (New == MostRecent)
+ return DMK_Replace;
+
// If the existing declaration is somewhere in the previous declaration
// chain of the new declaration, then prefer the new declaration.
for (Decl::redecl_iterator RD = New->redecls_begin(),
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index e2ec1ccebdcf..5f92cfffc6b0 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -16,8 +16,8 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "llvm/ADT/BitVector.h"
using namespace clang;
@@ -511,8 +511,14 @@ void JumpScopeChecker::VerifyJumps() {
for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
- CheckJump(SS, SC, SC->getLocStart(),
- diag::err_switch_into_protected_scope, 0,
+ SourceLocation Loc;
+ if (CaseStmt *CS = dyn_cast<CaseStmt>(SC))
+ Loc = CS->getLocStart();
+ else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC))
+ Loc = DS->getLocStart();
+ else
+ Loc = SC->getLocStart();
+ CheckJump(SS, SC, Loc, diag::err_switch_into_protected_scope, 0,
diag::warn_cxx98_compat_switch_into_protected_scope);
}
}
@@ -668,7 +674,7 @@ static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote) {
/// Return true if a particular note should be downgraded to a compatibility
/// warning in C++11 mode.
static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote) {
- return S.getLangOpts().CPlusPlus0x &&
+ return S.getLangOpts().CPlusPlus11 &&
InDiagNote == diag::note_protected_by_variable_non_pod;
}
diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index f930fb348a25..d85624ba6f64 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/MultiplexExternalSemaSource.h"
-
#include "clang/AST/DeclContextInternals.h"
#include "clang/Sema/Lookup.h"
@@ -82,19 +81,12 @@ CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers(
return 0;
}
-DeclContextLookupResult MultiplexExternalSemaSource::
+bool MultiplexExternalSemaSource::
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) {
- StoredDeclsList DeclsFound;
- DeclContextLookupResult lookup;
- for(size_t i = 0; i < Sources.size(); ++i) {
- lookup = Sources[i]->FindExternalVisibleDeclsByName(DC, Name);
- while(lookup.first != lookup.second) {
- if (!DeclsFound.HandleRedeclaration(*lookup.first))
- DeclsFound.AddSubsequentDecl(*lookup.first);
- lookup.first++;
- }
- }
- return DeclsFound.getLookupResult();
+ bool AnyDeclsFound = false;
+ for (size_t i = 0; i < Sources.size(); ++i)
+ AnyDeclsFound |= Sources[i]->FindExternalVisibleDeclsByName(DC, Name);
+ return AnyDeclsFound;
}
void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC){
@@ -201,6 +193,12 @@ void MultiplexExternalSemaSource::ReadKnownNamespaces(
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadKnownNamespaces(Namespaces);
}
+
+void MultiplexExternalSemaSource::ReadUndefinedButUsed(
+ llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined){
+ for(size_t i = 0; i < Sources.size(); ++i)
+ Sources[i]->ReadUndefinedButUsed(Undefined);
+}
bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){
for(size_t i = 0; i < Sources.size(); ++i)
@@ -239,10 +237,10 @@ void MultiplexExternalSemaSource::ReadDynamicClasses(
Sources[i]->ReadDynamicClasses(Decls);
}
-void MultiplexExternalSemaSource::ReadLocallyScopedExternalDecls(
+void MultiplexExternalSemaSource::ReadLocallyScopedExternCDecls(
SmallVectorImpl<NamedDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
- Sources[i]->ReadLocallyScopedExternalDecls(Decls);
+ Sources[i]->ReadLocallyScopedExternCDecls(Decls);
}
void MultiplexExternalSemaSource::ReadReferencedSelectors(
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 13a33b785b43..6bab9e80cbf7 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -13,21 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/DelayedDiagnostic.h"
#include "TargetAttributesSema.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallSet.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/Support/CrashRecoveryContext.h"
-#include "clang/Sema/CXXFieldCollector.h"
-#include "clang/Sema/TemplateDeduction.h"
-#include "clang/Sema/ExternalSemaSource.h"
-#include "clang/Sema/MultiplexExternalSemaSource.h"
-#include "clang/Sema/ObjCMethodList.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/SemaConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/DeclCXX.h"
@@ -36,11 +22,25 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/MultiplexExternalSemaSource.h"
+#include "clang/Sema/ObjCMethodList.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/Sema/TemplateDeduction.h"
+#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;
@@ -49,13 +49,14 @@ PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
PrintingPolicy Policy = Context.getPrintingPolicy();
Policy.Bool = Context.getLangOpts().Bool;
if (!Policy.Bool) {
- if (MacroInfo *BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) {
- Policy.Bool = BoolMacro->isObjectLike() &&
+ if (const MacroInfo *
+ BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) {
+ Policy.Bool = BoolMacro->isObjectLike() &&
BoolMacro->getNumTokens() == 1 &&
BoolMacro->getReplacementToken(0).is(tok::kw__Bool);
}
}
-
+
return Policy;
}
@@ -69,7 +70,7 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CodeCompleter)
- : TheTargetAttributesSema(0), ExternalSource(0),
+ : TheTargetAttributesSema(0), ExternalSource(0),
isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()),
LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
@@ -83,16 +84,16 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
NSStringDecl(0), StringWithUTF8StringMethod(0),
NSArrayDecl(0), ArrayWithObjectsMethod(0),
NSDictionaryDecl(0), DictionaryWithObjectsMethod(0),
- GlobalNewDeleteDeclared(false),
+ GlobalNewDeleteDeclared(false),
TUKind(TUKind),
NumSFINAEErrors(0), InFunctionDeclarator(0),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
CurrentInstantiationScope(0), TyposCorrected(0),
- AnalysisWarnings(*this)
+ AnalysisWarnings(*this), Ident_super(0)
{
TUScope = 0;
-
+
LoadedExternalKnownNamespaces = false;
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
NSNumberLiteralMethods[I] = 0;
@@ -104,7 +105,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,
+ PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
&Context);
ExprEvalContexts.push_back(
@@ -117,18 +118,18 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
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);
-
+
// Tell the external Sema source about this Sema object.
if (ExternalSemaSource *ExternalSema
= dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
ExternalSema->InitializeSema(*this);
// Initialize predefined 128-bit integer types, if needed.
- if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
+ if (PP.getTargetInfo().hasInt128Type()) {
// If either of the 128-bit integer types are unavailable to name lookup,
// define them now.
DeclarationName Int128 = &Context.Idents.get("__int128_t");
@@ -139,7 +140,7 @@ void Sema::Initialize() {
if (IdResolver.begin(UInt128) == IdResolver.end())
PushOnScopeChains(Context.getUInt128Decl(), TUScope);
}
-
+
// Initialize predefined Objective-C types:
if (PP.getLangOpts().ObjC1) {
@@ -154,7 +155,7 @@ void Sema::Initialize() {
DeclarationName Id = &Context.Idents.get("id");
if (IdResolver.begin(Id) == IdResolver.end())
PushOnScopeChains(Context.getObjCIdDecl(), TUScope);
-
+
// Create the built-in typedef for 'Class'.
DeclarationName Class = &Context.Idents.get("Class");
if (IdResolver.begin(Class) == IdResolver.end())
@@ -181,7 +182,7 @@ Sema::~Sema() {
delete FunctionScopes[I];
if (FunctionScopes.size() == 1)
delete FunctionScopes[0];
-
+
// Tell the SemaConsumer to forget about us; we're going out of scope.
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
SC->ForgetSema();
@@ -209,7 +210,7 @@ bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
// If we're in template instantiation, it's an error.
if (!ActiveTemplateInstantiations.empty())
return false;
-
+
// If that function's not in a system header, it's an error.
if (!Context.getSourceManager().isInSystemHeader(loc))
return false;
@@ -288,13 +289,13 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
// If this is a derived-to-base cast to a through a virtual base, we
// need a vtable.
- if (Kind == CK_DerivedToBase &&
+ if (Kind == CK_DerivedToBase &&
BasePathInvolvesVirtualBase(*BasePath)) {
QualType T = E->getType();
if (const PointerType *Pointer = T->getAs<PointerType>())
T = Pointer->getPointeeType();
if (const RecordType *RecordTy = T->getAs<RecordType>())
- MarkVTableUsed(E->getLocStart(),
+ MarkVTableUsed(E->getLocStart(),
cast<CXXRecordDecl>(RecordTy->getDecl()));
}
@@ -328,7 +329,10 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
- if (D->isUsed())
+ if (D->getMostRecentDecl()->isUsed())
+ return true;
+
+ if (D->hasExternalLinkage())
return true;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -348,7 +352,7 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
// UnusedFileScopedDecls stores the first declaration.
// The declaration may have become definition so check again.
- const VarDecl *DeclToCheck = VD->getDefinition();
+ const VarDecl *DeclToCheck = VD->getDefinition();
if (DeclToCheck)
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
@@ -363,68 +367,91 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
}
namespace {
- struct UndefinedInternal {
- NamedDecl *decl;
- FullSourceLoc useLoc;
-
- UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc)
- : decl(decl), useLoc(useLoc) {}
+ struct SortUndefinedButUsed {
+ const SourceManager &SM;
+ explicit SortUndefinedButUsed(SourceManager &SM) : SM(SM) {}
+
+ bool operator()(const std::pair<NamedDecl *, SourceLocation> &l,
+ const std::pair<NamedDecl *, SourceLocation> &r) const {
+ if (l.second.isValid() && !r.second.isValid())
+ return true;
+ if (!l.second.isValid() && r.second.isValid())
+ return false;
+ if (l.second != r.second)
+ return SM.isBeforeInTranslationUnit(l.second, r.second);
+ return SM.isBeforeInTranslationUnit(l.first->getLocation(),
+ r.first->getLocation());
+ }
};
-
- bool operator<(const UndefinedInternal &l, const UndefinedInternal &r) {
- return l.useLoc.isBeforeInTranslationUnitThan(r.useLoc);
- }
}
-/// checkUndefinedInternals - Check for undefined objects with internal linkage.
-static void checkUndefinedInternals(Sema &S) {
- if (S.UndefinedInternals.empty()) return;
-
- // Collect all the still-undefined entities with internal linkage.
- SmallVector<UndefinedInternal, 16> undefined;
- for (llvm::DenseMap<NamedDecl*,SourceLocation>::iterator
- i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end();
- i != e; ++i) {
- NamedDecl *decl = i->first;
+/// Obtains a sorted list of functions that are undefined but ODR-used.
+void Sema::getUndefinedButUsed(
+ SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) {
+ for (llvm::DenseMap<NamedDecl *, SourceLocation>::iterator
+ I = UndefinedButUsed.begin(), E = UndefinedButUsed.end();
+ I != E; ++I) {
+ NamedDecl *ND = I->first;
// Ignore attributes that have become invalid.
- if (decl->isInvalidDecl()) continue;
+ if (ND->isInvalidDecl()) continue;
// __attribute__((weakref)) is basically a definition.
- if (decl->hasAttr<WeakRefAttr>()) continue;
+ if (ND->hasAttr<WeakRefAttr>()) continue;
- if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
- if (fn->isPure() || fn->hasBody())
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+ if (FD->isDefined())
+ continue;
+ if (FD->hasExternalLinkage() &&
+ !FD->getMostRecentDecl()->isInlined())
continue;
} else {
- if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly)
+ if (cast<VarDecl>(ND)->hasDefinition() != VarDecl::DeclarationOnly)
+ continue;
+ if (ND->hasExternalLinkage())
continue;
}
- // We build a FullSourceLoc so that we can sort with array_pod_sort.
- FullSourceLoc loc(i->second, S.Context.getSourceManager());
- undefined.push_back(UndefinedInternal(decl, loc));
+ Undefined.push_back(std::make_pair(ND, I->second));
}
- if (undefined.empty()) return;
+ // Sort (in order of use site) so that we're not dependent on the iteration
+ // order through an llvm::DenseMap.
+ std::sort(Undefined.begin(), Undefined.end(),
+ SortUndefinedButUsed(Context.getSourceManager()));
+}
+
+/// checkUndefinedButUsed - Check for undefined objects with internal linkage
+/// or that are inline.
+static void checkUndefinedButUsed(Sema &S) {
+ if (S.UndefinedButUsed.empty()) return;
+
+ // Collect all the still-undefined entities with internal linkage.
+ SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
+ S.getUndefinedButUsed(Undefined);
+ if (Undefined.empty()) return;
- // Sort (in order of use site) so that we're not (as) dependent on
- // the iteration order through an llvm::DenseMap.
- llvm::array_pod_sort(undefined.begin(), undefined.end());
+ for (SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> >::iterator
+ I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
+ NamedDecl *ND = I->first;
- for (SmallVectorImpl<UndefinedInternal>::iterator
- i = undefined.begin(), e = undefined.end(); i != e; ++i) {
- NamedDecl *decl = i->decl;
- S.Diag(decl->getLocation(), diag::warn_undefined_internal)
- << isa<VarDecl>(decl) << decl;
- S.Diag(i->useLoc, diag::note_used_here);
+ if (ND->getLinkage() != ExternalLinkage) {
+ S.Diag(ND->getLocation(), diag::warn_undefined_internal)
+ << isa<VarDecl>(ND) << ND;
+ } else {
+ assert(cast<FunctionDecl>(ND)->getMostRecentDecl()->isInlined() &&
+ "used object requires definition but isn't inline or internal?");
+ S.Diag(ND->getLocation(), diag::warn_undefined_inline) << ND;
+ }
+ if (I->second.isValid())
+ S.Diag(I->second, diag::note_used_here);
}
}
void Sema::LoadExternalWeakUndeclaredIdentifiers() {
if (!ExternalSource)
return;
-
+
SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs;
ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs);
for (unsigned I = 0, N = WeakIDs.size(); I != N; ++I) {
@@ -432,7 +459,7 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() {
= WeakUndeclaredIdentifiers.find(WeakIDs[I].first);
if (Pos != WeakUndeclaredIdentifiers.end())
continue;
-
+
WeakUndeclaredIdentifiers.insert(WeakIDs[I]);
}
}
@@ -537,7 +564,7 @@ void Sema::ActOnEndOfTranslationUnit() {
I != E; ++I) {
assert(!(*I)->isDependentType() &&
"Should not see dependent types here!");
- if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(*I)) {
+ if (const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(*I)) {
const FunctionDecl *Definition = 0;
if (KeyFunction->hasBody(Definition))
MarkVTableUsed(Definition->getLocation(), *I, true);
@@ -561,9 +588,9 @@ void Sema::ActOnEndOfTranslationUnit() {
// or we need to perform template instantiations earlier.
PerformPendingInstantiations();
}
-
+
// Remove file scoped decls that turned out to be used.
- UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(0,
+ UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(0,
true),
UnusedFileScopedDecls.end(),
std::bind1st(std::ptr_fun(ShouldRemoveFromUnused),
@@ -589,24 +616,31 @@ void Sema::ActOnEndOfTranslationUnit() {
<< I->first;
}
+ if (LangOpts.CPlusPlus11 &&
+ Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle,
+ SourceLocation())
+ != DiagnosticsEngine::Ignored)
+ CheckDelegatingCtorCycles();
+
if (TUKind == TU_Module) {
// If we are building a module, resolve all of the exported declarations
// now.
if (Module *CurrentModule = PP.getCurrentModule()) {
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
-
- llvm::SmallVector<Module *, 2> Stack;
+
+ SmallVector<Module *, 2> Stack;
Stack.push_back(CurrentModule);
while (!Stack.empty()) {
Module *Mod = Stack.back();
Stack.pop_back();
-
- // Resolve the exported declarations.
+
+ // Resolve the exported declarations and conflicts.
// FIXME: Actually complain, once we figure out how to teach the
- // diagnostic client to deal with complains in the module map at this
+ // diagnostic client to deal with complaints in the module map at this
// point.
ModMap.resolveExports(Mod, /*Complain=*/false);
-
+ ModMap.resolveConflicts(Mod, /*Complain=*/false);
+
// Queue the submodules, so their exports will also be resolved.
for (Module::submodule_iterator Sub = Mod->submodule_begin(),
SubEnd = Mod->submodule_end();
@@ -615,12 +649,12 @@ void Sema::ActOnEndOfTranslationUnit() {
}
}
}
-
+
// Modules don't need any of the checking below.
TUScope = 0;
return;
}
-
+
// C99 6.9.2p2:
// A declaration of an identifier for an object that has file
// scope without an initializer, and without a storage-class
@@ -633,10 +667,10 @@ void Sema::ActOnEndOfTranslationUnit() {
// identifier, with the composite type as of the end of the
// translation unit, with an initializer equal to 0.
llvm::SmallSet<VarDecl *, 32> Seen;
- for (TentativeDefinitionsType::iterator
+ for (TentativeDefinitionsType::iterator
T = TentativeDefinitions.begin(ExternalSource),
TEnd = TentativeDefinitions.end();
- T != TEnd; ++T)
+ T != TEnd; ++T)
{
VarDecl *VD = (*T)->getActingDefinition();
@@ -673,12 +707,6 @@ void Sema::ActOnEndOfTranslationUnit() {
}
- if (LangOpts.CPlusPlus0x &&
- Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle,
- SourceLocation())
- != DiagnosticsEngine::Ignored)
- CheckDelegatingCtorCycles();
-
// If there were errors, disable 'unused' warnings since they will mostly be
// noise.
if (!Diags.hasErrorOccurred()) {
@@ -688,7 +716,7 @@ void Sema::ActOnEndOfTranslationUnit() {
E = UnusedFileScopedDecls.end(); I != E; ++I) {
if (ShouldRemoveFromUnused(this, *I))
continue;
-
+
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
const FunctionDecl *DiagD;
if (!FD->hasBody(DiagD))
@@ -700,7 +728,7 @@ void Sema::ActOnEndOfTranslationUnit() {
Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
<< DiagD->getDeclName();
else {
- if (FD->getStorageClassAsWritten() == SC_Static &&
+ if (FD->getStorageClass() == SC_Static &&
!FD->isInlineSpecified() &&
!SourceMgr.isFromMainFile(
SourceMgr.getExpansionLoc(FD->getLocation())))
@@ -730,7 +758,9 @@ void Sema::ActOnEndOfTranslationUnit() {
}
}
- checkUndefinedInternals(*this);
+ if (ExternalSource)
+ ExternalSource->ReadUndefinedButUsed(UndefinedButUsed);
+ checkUndefinedButUsed(*this);
}
if (Diags.getDiagnosticLevel(diag::warn_unused_private_field,
@@ -809,13 +839,13 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
// eliminnated. If it truly cannot be (for example, there is some reentrancy
// issue I am not seeing yet), then there should at least be a clarifying
// comment somewhere.
- if (llvm::Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) {
+ if (Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) {
switch (DiagnosticIDs::getDiagnosticSFINAEResponse(
Diags.getCurrentDiagID())) {
case DiagnosticIDs::SFINAE_Report:
// We'll report the diagnostic below.
break;
-
+
case DiagnosticIDs::SFINAE_SubstitutionFailure:
// Count this failure so that we know that template argument deduction
// has failed.
@@ -832,13 +862,13 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
Diags.setLastDiagnosticIgnored();
Diags.Clear();
return;
-
+
case DiagnosticIDs::SFINAE_AccessControl: {
// Per C++ Core Issue 1170, access control is part of SFINAE.
// Additionally, the AccessCheckingSFINAE flag can be used to temporarily
// make access control a part of SFINAE for the purposes of checking
// type traits.
- if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus0x)
+ if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus11)
break;
SourceLocation Loc = Diags.getCurrentDiagLoc();
@@ -882,10 +912,10 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
return;
}
}
-
+
// Set up the context's printing policy based on our current state.
Context.setPrintingPolicy(getPrintingPolicy());
-
+
// Emit the diagnostic.
if (!Diags.EmitCurrentDiagnostic())
return;
@@ -944,10 +974,10 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
/// \returns The scope corresponding to the given declaraion context, or NULL
/// if no such scope is open.
Scope *Sema::getScopeForContext(DeclContext *Ctx) {
-
+
if (!Ctx)
return 0;
-
+
Ctx = Ctx->getPrimaryContext();
for (Scope *S = getCurScope(); S; S = S->getParent()) {
// Ignore scopes that cannot have declarations. This is important for
@@ -957,7 +987,7 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) {
if (Ctx == Entity->getPrimaryContext())
return S;
}
-
+
return 0;
}
@@ -970,7 +1000,7 @@ void Sema::PushFunctionScope() {
FunctionScopes.push_back(FunctionScopes.back());
return;
}
-
+
FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
}
@@ -979,7 +1009,7 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
BlockScope, Block));
}
-void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
+void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
CXXMethodDecl *CallOperator) {
FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
CallOperator));
@@ -987,9 +1017,9 @@ void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, const BlockExpr *blkExpr) {
- FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
assert(!FunctionScopes.empty() && "mismatched push/pop!");
-
+
// Issue any analysis-based warnings.
if (WP && D)
AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr);
@@ -1028,15 +1058,15 @@ bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
return 0;
-
- return dyn_cast<BlockScopeInfo>(FunctionScopes.back());
+
+ return dyn_cast<BlockScopeInfo>(FunctionScopes.back());
}
LambdaScopeInfo *Sema::getCurLambda() {
if (FunctionScopes.empty())
return 0;
-
- return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+
+ return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
}
void Sema::ActOnComment(SourceRange Comment) {
@@ -1071,7 +1101,11 @@ ExternalSemaSource::~ExternalSemaSource() {}
void ExternalSemaSource::ReadMethodPool(Selector Sel) { }
void ExternalSemaSource::ReadKnownNamespaces(
- SmallVectorImpl<NamespaceDecl *> &Namespaces) {
+ SmallVectorImpl<NamespaceDecl *> &Namespaces) {
+}
+
+void ExternalSemaSource::ReadUndefinedButUsed(
+ llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) {
}
void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
@@ -1248,7 +1282,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
// actually a CallExpr.
SourceLocation ParenInsertionLoc =
PP.getLocForEndOfToken(Range.getEnd());
- Diag(Loc, PD)
+ Diag(Loc, PD)
<< /*zero-arg*/ 1 << Range
<< (IsCallableWithAppend(E.get())
? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
@@ -1269,3 +1303,9 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
E = ExprError();
return true;
}
+
+IdentifierInfo *Sema::getSuperIdentifier() const {
+ if (!Ident_super)
+ Ident_super = &Context.Idents.get("super");
+ return Ident_super;
+}
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 58b1a51ae573..79a9d3c9fdc7 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -12,9 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/DelayedDiagnostic.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
@@ -22,6 +19,9 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
using namespace clang;
using namespace sema;
@@ -217,6 +217,15 @@ struct AccessTarget : public AccessedEntity {
return DeclaringClass;
}
+ /// The "effective" naming class is the canonical non-anonymous
+ /// class containing the actual naming class.
+ const CXXRecordDecl *getEffectiveNamingClass() const {
+ const CXXRecordDecl *namingClass = getNamingClass();
+ while (namingClass->isAnonymousStructOrUnion())
+ namingClass = cast<CXXRecordDecl>(namingClass->getParent());
+ return namingClass->getCanonicalDecl();
+ }
+
private:
void initialize() {
HasInstanceContext = (isMemberAccess() &&
@@ -1023,8 +1032,7 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
assert(Target.isMemberAccess());
- const CXXRecordDecl *NamingClass = Target.getNamingClass();
- NamingClass = NamingClass->getCanonicalDecl();
+ const CXXRecordDecl *NamingClass = Target.getEffectiveNamingClass();
for (EffectiveContext::record_iterator
I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
@@ -1089,129 +1097,173 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
return false;
}
+/// We are unable to access a given declaration due to its direct
+/// access control; diagnose that.
+static void diagnoseBadDirectAccess(Sema &S,
+ const EffectiveContext &EC,
+ AccessTarget &entity) {
+ assert(entity.isMemberAccess());
+ NamedDecl *D = entity.getTargetDecl();
+
+ if (D->getAccess() == AS_protected &&
+ TryDiagnoseProtectedAccess(S, EC, entity))
+ return;
+
+ // Find an original declaration.
+ while (D->isOutOfLine()) {
+ NamedDecl *PrevDecl = 0;
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ PrevDecl = VD->getPreviousDecl();
+ else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ PrevDecl = FD->getPreviousDecl();
+ else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
+ PrevDecl = TND->getPreviousDecl();
+ else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
+ break;
+ PrevDecl = TD->getPreviousDecl();
+ }
+ if (!PrevDecl) break;
+ D = PrevDecl;
+ }
+
+ CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
+ Decl *ImmediateChild;
+ if (D->getDeclContext() == DeclaringClass)
+ ImmediateChild = D;
+ else {
+ DeclContext *DC = D->getDeclContext();
+ while (DC->getParent() != DeclaringClass)
+ DC = DC->getParent();
+ ImmediateChild = cast<Decl>(DC);
+ }
+
+ // Check whether there's an AccessSpecDecl preceding this in the
+ // chain of the DeclContext.
+ bool isImplicit = true;
+ for (CXXRecordDecl::decl_iterator
+ I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
+ I != E; ++I) {
+ if (*I == ImmediateChild) break;
+ if (isa<AccessSpecDecl>(*I)) {
+ isImplicit = false;
+ break;
+ }
+ }
+
+ S.Diag(D->getLocation(), diag::note_access_natural)
+ << (unsigned) (D->getAccess() == AS_protected)
+ << isImplicit;
+}
+
/// Diagnose the path which caused the given declaration or base class
/// to become inaccessible.
static void DiagnoseAccessPath(Sema &S,
const EffectiveContext &EC,
- AccessTarget &Entity) {
- AccessSpecifier Access = Entity.getAccess();
+ AccessTarget &entity) {
+ // Save the instance context to preserve invariants.
+ AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext();
- NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
- const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
+ // This basically repeats the main algorithm but keeps some more
+ // information.
- // Easy case: the decl's natural access determined its path access.
- // We have to check against AS_private here in case Access is AS_none,
- // indicating a non-public member of a private base class.
- if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
- switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
- case AR_inaccessible: {
- if (Access == AS_protected &&
- TryDiagnoseProtectedAccess(S, EC, Entity))
- return;
-
- // Find an original declaration.
- while (D->isOutOfLine()) {
- NamedDecl *PrevDecl = 0;
- if (VarDecl *VD = dyn_cast<VarDecl>(D))
- PrevDecl = VD->getPreviousDecl();
- else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- PrevDecl = FD->getPreviousDecl();
- else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
- PrevDecl = TND->getPreviousDecl();
- else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
- break;
- PrevDecl = TD->getPreviousDecl();
- }
- if (!PrevDecl) break;
- D = PrevDecl;
- }
+ // The natural access so far.
+ AccessSpecifier accessSoFar = AS_public;
- CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
- Decl *ImmediateChild;
- if (D->getDeclContext() == DeclaringClass)
- ImmediateChild = D;
- else {
- DeclContext *DC = D->getDeclContext();
- while (DC->getParent() != DeclaringClass)
- DC = DC->getParent();
- ImmediateChild = cast<Decl>(DC);
- }
-
- // Check whether there's an AccessSpecDecl preceding this in the
- // chain of the DeclContext.
- bool Implicit = true;
- for (CXXRecordDecl::decl_iterator
- I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
- I != E; ++I) {
- if (*I == ImmediateChild) break;
- if (isa<AccessSpecDecl>(*I)) {
- Implicit = false;
- break;
- }
- }
+ // Check whether we have special rights to the declaring class.
+ if (entity.isMemberAccess()) {
+ NamedDecl *D = entity.getTargetDecl();
+ accessSoFar = D->getAccess();
+ const CXXRecordDecl *declaringClass = entity.getDeclaringClass();
- S.Diag(D->getLocation(), diag::note_access_natural)
- << (unsigned) (Access == AS_protected)
- << Implicit;
- return;
- }
+ switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) {
+ // If the declaration is accessible when named in its declaring
+ // class, then we must be constrained by the path.
+ case AR_accessible:
+ accessSoFar = AS_public;
+ entity.suppressInstanceContext();
+ break;
- case AR_accessible: break;
+ case AR_inaccessible:
+ if (accessSoFar == AS_private ||
+ declaringClass == entity.getEffectiveNamingClass())
+ return diagnoseBadDirectAccess(S, EC, entity);
+ break;
case AR_dependent:
- llvm_unreachable("can't diagnose dependent access failures");
+ llvm_unreachable("cannot diagnose dependent access");
}
}
- CXXBasePaths Paths;
- CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
+ CXXBasePaths paths;
+ CXXBasePath &path = *FindBestPath(S, EC, entity, accessSoFar, paths);
+ assert(path.Access != AS_public);
- CXXBasePath::iterator I = Path.end(), E = Path.begin();
- while (I != E) {
- --I;
+ CXXBasePath::iterator i = path.end(), e = path.begin();
+ CXXBasePath::iterator constrainingBase = i;
+ while (i != e) {
+ --i;
- const CXXBaseSpecifier *BS = I->Base;
- AccessSpecifier BaseAccess = BS->getAccessSpecifier();
+ assert(accessSoFar != AS_none && accessSoFar != AS_private);
- // If this is public inheritance, or the derived class is a friend,
- // skip this step.
- if (BaseAccess == AS_public)
- continue;
+ // Is the entity accessible when named in the deriving class, as
+ // modified by the base specifier?
+ const CXXRecordDecl *derivingClass = i->Class->getCanonicalDecl();
+ const CXXBaseSpecifier *base = i->Base;
- switch (GetFriendKind(S, EC, I->Class)) {
- case AR_accessible: continue;
+ // If the access to this base is worse than the access we have to
+ // the declaration, remember it.
+ AccessSpecifier baseAccess = base->getAccessSpecifier();
+ if (baseAccess > accessSoFar) {
+ constrainingBase = i;
+ accessSoFar = baseAccess;
+ }
+
+ switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) {
case AR_inaccessible: break;
+ case AR_accessible:
+ accessSoFar = AS_public;
+ entity.suppressInstanceContext();
+ constrainingBase = 0;
+ break;
case AR_dependent:
- llvm_unreachable("can't diagnose dependent access failures");
+ llvm_unreachable("cannot diagnose dependent access");
}
- // Check whether this base specifier is the tighest point
- // constraining access. We have to check against AS_private for
- // the same reasons as above.
- if (BaseAccess == AS_private || BaseAccess >= Access) {
-
- // We're constrained by inheritance, but we want to say
- // "declared private here" if we're diagnosing a hierarchy
- // conversion and this is the final step.
- unsigned diagnostic;
- if (D) diagnostic = diag::note_access_constrained_by_path;
- else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
- else diagnostic = diag::note_access_constrained_by_path;
-
- S.Diag(BS->getSourceRange().getBegin(), diagnostic)
- << BS->getSourceRange()
- << (BaseAccess == AS_protected)
- << (BS->getAccessSpecifierAsWritten() == AS_none);
-
- if (D)
- S.Diag(D->getLocation(), diag::note_field_decl);
-
- return;
+ // If this was private inheritance, but we don't have access to
+ // the deriving class, we're done.
+ if (accessSoFar == AS_private) {
+ assert(baseAccess == AS_private);
+ assert(constrainingBase == i);
+ break;
}
}
- llvm_unreachable("access not apparently constrained by path");
+ // If we don't have a constraining base, the access failure must be
+ // due to the original declaration.
+ if (constrainingBase == path.end())
+ return diagnoseBadDirectAccess(S, EC, entity);
+
+ // We're constrained by inheritance, but we want to say
+ // "declared private here" if we're diagnosing a hierarchy
+ // conversion and this is the final step.
+ unsigned diagnostic;
+ if (entity.isMemberAccess() ||
+ constrainingBase + 1 != path.end()) {
+ diagnostic = diag::note_access_constrained_by_path;
+ } else {
+ diagnostic = diag::note_access_natural;
+ }
+
+ const CXXBaseSpecifier *base = constrainingBase->Base;
+
+ S.Diag(base->getSourceRange().getBegin(), diagnostic)
+ << base->getSourceRange()
+ << (base->getAccessSpecifier() == AS_protected)
+ << (base->getAccessSpecifierAsWritten() == AS_none);
+
+ if (entity.isMemberAccess())
+ S.Diag(entity.getTargetDecl()->getLocation(), diag::note_field_decl);
}
static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
@@ -1273,10 +1325,7 @@ static AccessResult IsAccessible(Sema &S,
const EffectiveContext &EC,
AccessTarget &Entity) {
// Determine the actual naming class.
- CXXRecordDecl *NamingClass = Entity.getNamingClass();
- while (NamingClass->isAnonymousStructOrUnion())
- NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
- NamingClass = NamingClass->getCanonicalDecl();
+ const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass();
AccessSpecifier UnprivilegedAccess = Entity.getAccess();
assert(UnprivilegedAccess != AS_public && "public access not weeded out");
@@ -1317,7 +1366,13 @@ static AccessResult IsAccessible(Sema &S,
FinalAccess = Target->getAccess();
switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
case AR_accessible:
+ // Target is accessible at EC when named in its declaring class.
+ // We can now hill-climb and simply check whether the declaring
+ // class is accessible as a base of the naming class. This is
+ // equivalent to checking the access of a notional public
+ // member with no instance context.
FinalAccess = AS_public;
+ Entity.suppressInstanceContext();
break;
case AR_inaccessible: break;
case AR_dependent: return AR_dependent; // see above
@@ -1325,8 +1380,6 @@ static AccessResult IsAccessible(Sema &S,
if (DeclaringClass == NamingClass)
return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
-
- Entity.suppressInstanceContext();
} else {
FinalAccess = AS_public;
}
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index f1154c1a8aeb..e12bbde0d0dd 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -13,11 +13,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Lookup.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -309,7 +309,8 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) {
if (!VisContext)
return;
- if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility())
+ NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue))
return;
VisStack *Stack = static_cast<VisStack*>(VisContext);
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 15bfd1ce6294..01ac8f7fb62d 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -12,21 +12,21 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Template.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
-#include "TypeLocBuilder.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
/// \brief Find the current instantiation that associated with the given type.
-static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
+static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
DeclContext *CurContext) {
if (T.isNull())
return 0;
@@ -34,16 +34,10 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (!T->isDependentType())
+ if (!Record->isDependentContext() ||
+ Record->isCurrentInstantiation(CurContext))
return Record;
- // This may be a member of a class template or class template partial
- // specialization. If it's part of the current semantic context, then it's
- // an injected-class-name;
- for (; !CurContext->isFileContext(); CurContext = CurContext->getParent())
- if (CurContext->Equals(Record))
- return Record;
-
return 0;
} else if (isa<InjectedClassNameType>(Ty))
return cast<InjectedClassNameType>(Ty)->getDecl();
@@ -84,8 +78,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
if (!SS.isSet() || SS.isInvalid())
return 0;
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NestedNameSpecifier *NNS = SS.getScopeRep();
if (NNS->isDependent()) {
// If this nested-name-specifier refers to the current
// instantiation, return its DeclContext.
@@ -164,9 +157,7 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
if (!SS.isSet() || SS.isInvalid())
return false;
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- return NNS->isDependent();
+ return SS.getScopeRep()->isDependent();
}
// \brief Determine whether this C++ scope specifier refers to an
@@ -176,9 +167,7 @@ bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) {
if (!isDependentScopeSpecifier(SS))
return false;
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- return getCurrentInstantiationOf(NNS) == 0;
+ return getCurrentInstantiationOf(SS.getScopeRep()) == 0;
}
/// \brief If the given nested name specifier refers to the current
@@ -269,7 +258,7 @@ bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
/// \brief Determines whether the given declaration is an valid acceptable
/// result for name lookup of a nested-name-specifier.
-bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
+bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
if (!SD)
return false;
@@ -285,13 +274,13 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
if (T->isDependentType())
return true;
- else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
+ else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
if (TD->getUnderlyingType()->isRecordType() ||
- (Context.getLangOpts().CPlusPlus0x &&
+ (Context.getLangOpts().CPlusPlus11 &&
TD->getUnderlyingType()->isEnumeralType()))
return true;
} else if (isa<RecordDecl>(SD) ||
- (Context.getLangOpts().CPlusPlus0x && isa<EnumDecl>(SD)))
+ (Context.getLangOpts().CPlusPlus11 && isa<EnumDecl>(SD)))
return true;
return false;
@@ -540,7 +529,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
NamedDecl *SD = Found.getAsSingle<NamedDecl>();
if (isAcceptableNestedNameSpecifier(SD)) {
if (!ObjectType.isNull() && !ObjectTypeSearchedInScope &&
- !getLangOpts().CPlusPlus0x) {
+ !getLangOpts().CPlusPlus11) {
// C++03 [basic.lookup.classref]p4:
// [...] If the name is found in both contexts, the
// class-name-or-namespace-name shall refer to the same entity.
@@ -775,8 +764,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){
// Handle a dependent template specialization for which we cannot resolve
// the template name.
- assert(DTN->getQualifier()
- == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+ assert(DTN->getQualifier() == SS.getScopeRep());
QualType T = Context.getDependentTemplateSpecializationType(ETK_None,
DTN->getQualifier(),
DTN->getIdentifier(),
@@ -883,8 +871,7 @@ void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr,
bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
- NestedNameSpecifier *Qualifier =
- static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ NestedNameSpecifier *Qualifier = SS.getScopeRep();
// There are only two places a well-formed program may qualify a
// declarator: first, when defining a namespace or class member
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index bf25c6178541..e2a408476639 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -15,12 +15,13 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/ExprObjC.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/RecordLayout.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Sema/Initialization.h"
#include "llvm/ADT/SmallVector.h"
#include <set>
using namespace clang;
@@ -258,7 +259,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
}
return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.SrcExpr.take(), DestTInfo,
- OpLoc, Parens.getEnd()));
+ OpLoc, Parens.getEnd(),
+ AngleBrackets));
case tok::kw_dynamic_cast: {
if (!TypeDependent) {
@@ -269,7 +271,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
&Op.BasePath, DestTInfo,
- OpLoc, Parens.getEnd()));
+ OpLoc, Parens.getEnd(),
+ AngleBrackets));
}
case tok::kw_reinterpret_cast: {
if (!TypeDependent) {
@@ -280,7 +283,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
0, DestTInfo, OpLoc,
- Parens.getEnd()));
+ Parens.getEnd(),
+ AngleBrackets));
}
case tok::kw_static_cast: {
if (!TypeDependent) {
@@ -292,7 +296,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
&Op.BasePath, DestTInfo,
- OpLoc, Parens.getEnd()));
+ OpLoc, Parens.getEnd(),
+ AngleBrackets));
}
}
}
@@ -678,6 +683,98 @@ void CastOperation::CheckConstCast() {
<< SrcExpr.get()->getType() << DestType << OpRange;
}
+/// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast
+/// or downcast between respective pointers or references.
+static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
+ QualType DestType,
+ SourceRange OpRange) {
+ QualType SrcType = SrcExpr->getType();
+ // When casting from pointer or reference, get pointee type; use original
+ // type otherwise.
+ const CXXRecordDecl *SrcPointeeRD = SrcType->getPointeeCXXRecordDecl();
+ const CXXRecordDecl *SrcRD =
+ SrcPointeeRD ? SrcPointeeRD : SrcType->getAsCXXRecordDecl();
+
+ // Examining subobjects for records is only possible if the complete and
+ // valid definition is available. Also, template instantiation is not
+ // allowed here.
+ if (!SrcRD || !SrcRD->isCompleteDefinition() || SrcRD->isInvalidDecl())
+ return;
+
+ const CXXRecordDecl *DestRD = DestType->getPointeeCXXRecordDecl();
+
+ if (!DestRD || !DestRD->isCompleteDefinition() || DestRD->isInvalidDecl())
+ return;
+
+ enum {
+ ReinterpretUpcast,
+ ReinterpretDowncast
+ } ReinterpretKind;
+
+ CXXBasePaths BasePaths;
+
+ if (SrcRD->isDerivedFrom(DestRD, BasePaths))
+ ReinterpretKind = ReinterpretUpcast;
+ else if (DestRD->isDerivedFrom(SrcRD, BasePaths))
+ ReinterpretKind = ReinterpretDowncast;
+ else
+ return;
+
+ bool VirtualBase = true;
+ bool NonZeroOffset = false;
+ for (CXXBasePaths::const_paths_iterator I = BasePaths.begin(),
+ E = BasePaths.end();
+ I != E; ++I) {
+ const CXXBasePath &Path = *I;
+ CharUnits Offset = CharUnits::Zero();
+ bool IsVirtual = false;
+ for (CXXBasePath::const_iterator IElem = Path.begin(), EElem = Path.end();
+ IElem != EElem; ++IElem) {
+ IsVirtual = IElem->Base->isVirtual();
+ if (IsVirtual)
+ break;
+ const CXXRecordDecl *BaseRD = IElem->Base->getType()->getAsCXXRecordDecl();
+ assert(BaseRD && "Base type should be a valid unqualified class type");
+ // Don't check if any base has invalid declaration or has no definition
+ // since it has no layout info.
+ const CXXRecordDecl *Class = IElem->Class,
+ *ClassDefinition = Class->getDefinition();
+ if (Class->isInvalidDecl() || !ClassDefinition ||
+ !ClassDefinition->isCompleteDefinition())
+ return;
+
+ const ASTRecordLayout &DerivedLayout =
+ Self.Context.getASTRecordLayout(Class);
+ Offset += DerivedLayout.getBaseClassOffset(BaseRD);
+ }
+ if (!IsVirtual) {
+ // Don't warn if any path is a non-virtually derived base at offset zero.
+ if (Offset.isZero())
+ return;
+ // Offset makes sense only for non-virtual bases.
+ else
+ NonZeroOffset = true;
+ }
+ VirtualBase = VirtualBase && IsVirtual;
+ }
+
+ assert((VirtualBase || NonZeroOffset) &&
+ "Should have returned if has non-virtual base with zero offset");
+
+ QualType BaseType =
+ ReinterpretKind == ReinterpretUpcast? DestType : SrcType;
+ QualType DerivedType =
+ ReinterpretKind == ReinterpretUpcast? SrcType : DestType;
+
+ SourceLocation BeginLoc = OpRange.getBegin();
+ Self.Diag(BeginLoc, diag::warn_reinterpret_different_from_static)
+ << DerivedType << BaseType << !VirtualBase << ReinterpretKind
+ << OpRange;
+ Self.Diag(BeginLoc, diag::note_reinterpret_updowncast_use_static)
+ << ReinterpretKind
+ << FixItHint::CreateReplacement(BeginLoc, "static_cast");
+}
+
/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is
/// valid.
/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code
@@ -710,8 +807,10 @@ void CastOperation::CheckReinterpretCast() {
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(),
DestType, /*listInitialization=*/false);
}
- } else if (tcr == TC_Success && Self.getLangOpts().ObjCAutoRefCount) {
- checkObjCARCConversion(Sema::CCK_OtherCast);
+ } else if (tcr == TC_Success) {
+ if (Self.getLangOpts().ObjCAutoRefCount)
+ checkObjCARCConversion(Sema::CCK_OtherCast);
+ DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange);
}
}
@@ -1479,6 +1578,8 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
static void DiagnoseCastOfObjCSEL(Sema &Self, const ExprResult &SrcExpr,
QualType DestType) {
QualType SrcType = SrcExpr.get()->getType();
+ if (Self.Context.hasSameType(SrcType, DestType))
+ return;
if (const PointerType *SrcPtrTy = SrcType->getAs<PointerType>())
if (SrcPtrTy->isObjCSelType()) {
QualType DT = DestType;
@@ -1773,7 +1874,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
// FIXME: Conditionally-supported behavior should be configurable in the
// TargetInfo or similar.
Self.Diag(OpRange.getBegin(),
- Self.getLangOpts().CPlusPlus0x ?
+ Self.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
<< OpRange;
return TC_Success;
@@ -1782,7 +1883,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
if (DestType->isFunctionPointerType()) {
// See above.
Self.Diag(OpRange.getBegin(),
- Self.getLangOpts().CPlusPlus0x ?
+ Self.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
<< OpRange;
return TC_Success;
@@ -2102,6 +2203,15 @@ void CastOperation::CheckCStyleCast() {
}
}
+ if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().cl_khr_fp16) {
+ if (DestType->isHalfType()) {
+ Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half)
+ << DestType << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
+ return;
+ }
+ }
+
// ARC imposes extra restrictions on casts.
if (Self.getLangOpts().ObjCAutoRefCount) {
checkObjCARCConversion(Sema::CCK_CStyleCast);
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 692a210ef304..4e11b3aa7920 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -12,32 +12,31 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Analysis/Analyses/FormatString.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/AST/EvaluatedExprVisitor.h"
-#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Sema.h"
#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/raw_ostream.h"
-#include "clang/Basic/TargetBuiltins.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/ConvertUTF.h"
#include <limits>
using namespace clang;
using namespace sema;
@@ -488,8 +487,8 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
/// Handles the checks for format strings, non-POD arguments to vararg
/// functions, and NULL arguments passed to non-NULL parameters.
-void Sema::checkCall(NamedDecl *FDecl, Expr **Args,
- unsigned NumArgs,
+void Sema::checkCall(NamedDecl *FDecl,
+ ArrayRef<const Expr *> Args,
unsigned NumProtoArgs,
bool IsMemberFunction,
SourceLocation Loc,
@@ -503,41 +502,40 @@ void Sema::checkCall(NamedDecl *FDecl, Expr **Args,
for (specific_attr_iterator<FormatAttr>
I = FDecl->specific_attr_begin<FormatAttr>(),
E = FDecl->specific_attr_end<FormatAttr>(); I != E ; ++I)
- if (CheckFormatArguments(*I, Args, NumArgs, IsMemberFunction, CallType,
- Loc, Range))
+ if (CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range))
HandledFormatString = true;
// Refuse POD arguments that weren't caught by the format string
// checks above.
if (!HandledFormatString && CallType != VariadicDoesNotApply)
- for (unsigned ArgIdx = NumProtoArgs; ArgIdx < NumArgs; ++ArgIdx) {
+ for (unsigned ArgIdx = NumProtoArgs; ArgIdx < Args.size(); ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
- if (Expr *Arg = Args[ArgIdx])
+ if (const Expr *Arg = Args[ArgIdx])
variadicArgumentPODCheck(Arg, CallType);
}
for (specific_attr_iterator<NonNullAttr>
I = FDecl->specific_attr_begin<NonNullAttr>(),
E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I)
- CheckNonNullArguments(*I, Args, Loc);
+ CheckNonNullArguments(*I, Args.data(), Loc);
// Type safety checking.
for (specific_attr_iterator<ArgumentWithTypeTagAttr>
i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(),
e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>(); i != e; ++i) {
- CheckArgumentWithTypeTag(*i, Args);
+ CheckArgumentWithTypeTag(*i, Args.data());
}
}
/// CheckConstructorCall - Check a constructor call for correctness and safety
/// properties not enforced by the C type system.
-void Sema::CheckConstructorCall(FunctionDecl *FDecl, Expr **Args,
- unsigned NumArgs,
+void Sema::CheckConstructorCall(FunctionDecl *FDecl,
+ ArrayRef<const Expr *> Args,
const FunctionProtoType *Proto,
SourceLocation Loc) {
VariadicCallType CallType =
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
- checkCall(FDecl, Args, NumArgs, Proto->getNumArgs(),
+ checkCall(FDecl, Args, Proto->getNumArgs(),
/*IsMemberFunction=*/true, Loc, SourceRange(), CallType);
}
@@ -561,7 +559,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
++Args;
--NumArgs;
}
- checkCall(FDecl, Args, NumArgs, NumProtoArgs,
+ checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs),
+ NumProtoArgs,
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -591,7 +590,8 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
VariadicCallType CallType =
Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply;
- checkCall(Method, Args, NumArgs, Method->param_size(),
+ checkCall(Method, llvm::makeArrayRef<const Expr *>(Args, NumArgs),
+ Method->param_size(),
/*IsMemberFunction=*/false,
lbrac, Method->getSourceRange(), CallType);
@@ -612,7 +612,9 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall,
Proto && Proto->isVariadic() ? VariadicBlock : VariadicDoesNotApply ;
unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
- checkCall(NDecl, TheCall->getArgs(), TheCall->getNumArgs(),
+ checkCall(NDecl,
+ llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
+ TheCall->getNumArgs()),
NumProtoArgs, /*IsMemberFunction=*/false,
TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -1646,8 +1648,8 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
// format string, we will usually need to emit a warning.
// True string literals are then checked by CheckFormatString.
Sema::StringLiteralCheckType
-Sema::checkFormatStringExpr(const Expr *E, Expr **Args,
- unsigned NumArgs, bool HasVAListArg,
+Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
+ bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg,
FormatStringType Type, VariadicCallType CallType,
bool inFunctionCall) {
@@ -1672,13 +1674,13 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args,
const AbstractConditionalOperator *C =
cast<AbstractConditionalOperator>(E);
StringLiteralCheckType Left =
- checkFormatStringExpr(C->getTrueExpr(), Args, NumArgs,
+ checkFormatStringExpr(C->getTrueExpr(), Args,
HasVAListArg, format_idx, firstDataArg,
Type, CallType, inFunctionCall);
if (Left == SLCT_NotALiteral)
return SLCT_NotALiteral;
StringLiteralCheckType Right =
- checkFormatStringExpr(C->getFalseExpr(), Args, NumArgs,
+ checkFormatStringExpr(C->getFalseExpr(), Args,
HasVAListArg, format_idx, firstDataArg,
Type, CallType, inFunctionCall);
return Left < Right ? Left : Right;
@@ -1729,7 +1731,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args,
if (InitList->isStringLiteralInit())
Init = InitList->getInit(0)->IgnoreParenImpCasts();
}
- return checkFormatStringExpr(Init, Args, NumArgs,
+ return checkFormatStringExpr(Init, Args,
HasVAListArg, format_idx,
firstDataArg, Type, CallType,
/*inFunctionCall*/false);
@@ -1787,7 +1789,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args,
--ArgIndex;
const Expr *Arg = CE->getArg(ArgIndex - 1);
- return checkFormatStringExpr(Arg, Args, NumArgs,
+ return checkFormatStringExpr(Arg, Args,
HasVAListArg, format_idx, firstDataArg,
Type, CallType, inFunctionCall);
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
@@ -1795,7 +1797,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args,
if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
const Expr *Arg = CE->getArg(0);
- return checkFormatStringExpr(Arg, Args, NumArgs,
+ return checkFormatStringExpr(Arg, Args,
HasVAListArg, format_idx,
firstDataArg, Type, CallType,
inFunctionCall);
@@ -1815,7 +1817,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args,
StrE = cast<StringLiteral>(E);
if (StrE) {
- CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx,
+ CheckFormatString(StrE, E, Args, HasVAListArg, format_idx,
firstDataArg, Type, inFunctionCall, CallType);
return SLCT_CheckedLiteral;
}
@@ -1836,8 +1838,20 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
e = NonNull->args_end();
i != e; ++i) {
const Expr *ArgExpr = ExprArgs[*i];
- if (ArgExpr->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNotNull))
+
+ // As a special case, transparent unions initialized with zero are
+ // considered null for the purposes of the nonnull attribute.
+ if (const RecordType *UT = ArgExpr->getType()->getAsUnionType()) {
+ if (UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (const CompoundLiteralExpr *CLE =
+ dyn_cast<CompoundLiteralExpr>(ArgExpr))
+ if (const InitListExpr *ILE =
+ dyn_cast<InitListExpr>(CLE->getInitializer()))
+ ArgExpr = ILE->getInit(0);
+ }
+
+ bool Result;
+ if (ArgExpr->EvaluateAsBooleanCondition(Result, Context) && !Result)
Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
}
}
@@ -1856,25 +1870,26 @@ Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
/// CheckFormatArguments - Check calls to printf and scanf (and similar
/// functions) for correct use of format strings.
/// Returns true if a format string has been fully checked.
-bool Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args,
- unsigned NumArgs, bool IsCXXMember,
+bool Sema::CheckFormatArguments(const FormatAttr *Format,
+ ArrayRef<const Expr *> Args,
+ bool IsCXXMember,
VariadicCallType CallType,
SourceLocation Loc, SourceRange Range) {
FormatStringInfo FSI;
if (getFormatStringInfo(Format, IsCXXMember, &FSI))
- return CheckFormatArguments(Args, NumArgs, FSI.HasVAListArg, FSI.FormatIdx,
+ return CheckFormatArguments(Args, FSI.HasVAListArg, FSI.FormatIdx,
FSI.FirstDataArg, GetFormatStringType(Format),
CallType, Loc, Range);
return false;
}
-bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs,
+bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
bool HasVAListArg, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
VariadicCallType CallType,
SourceLocation Loc, SourceRange Range) {
// CHECK: printf/scanf-like function is called with no format string.
- if (format_idx >= NumArgs) {
+ if (format_idx >= Args.size()) {
Diag(Loc, diag::warn_missing_format_string) << Range;
return false;
}
@@ -1894,7 +1909,7 @@ bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs,
// ObjC string uses the same format specifiers as C string, so we can use
// the same format string checking logic for both ObjC and C strings.
StringLiteralCheckType CT =
- checkFormatStringExpr(OrigFormatExpr, Args, NumArgs, HasVAListArg,
+ checkFormatStringExpr(OrigFormatExpr, Args, HasVAListArg,
format_idx, firstDataArg, Type, CallType);
if (CT != SLCT_NotALiteral)
// Literal format string found, check done!
@@ -1915,7 +1930,7 @@ bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs,
// If there are no arguments specified, warn with -Wformat-security, otherwise
// warn only with -Wformat-nonliteral.
- if (NumArgs == format_idx+1)
+ if (Args.size() == format_idx+1)
Diag(Args[format_idx]->getLocStart(),
diag::warn_format_nonliteral_noargs)
<< OrigFormatExpr->getSourceRange();
@@ -1936,8 +1951,7 @@ protected:
const unsigned NumDataArgs;
const char *Beg; // Start of format string.
const bool HasVAListArg;
- const Expr * const *Args;
- const unsigned NumArgs;
+ ArrayRef<const Expr *> Args;
unsigned FormatIdx;
llvm::BitVector CoveredArgs;
bool usesPositionalArgs;
@@ -1948,13 +1962,13 @@ public:
CheckFormatHandler(Sema &s, const StringLiteral *fexpr,
const Expr *origFormatExpr, unsigned firstDataArg,
unsigned numDataArgs, const char *beg, bool hasVAListArg,
- Expr **args, unsigned numArgs,
+ ArrayRef<const Expr *> Args,
unsigned formatIdx, bool inFunctionCall,
Sema::VariadicCallType callType)
: S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
FirstDataArg(firstDataArg), NumDataArgs(numDataArgs),
Beg(beg), HasVAListArg(hasVAListArg),
- Args(args), NumArgs(numArgs), FormatIdx(formatIdx),
+ Args(Args), FormatIdx(formatIdx),
usesPositionalArgs(false), atFirstArg(true),
inFunctionCall(inFunctionCall), CallType(callType) {
CoveredArgs.resize(numDataArgs);
@@ -2066,7 +2080,7 @@ void CheckFormatHandler::HandleInvalidLengthModifier(
CharSourceRange LMRange = getSpecifierRange(LM.getStart(), LM.getLength());
// See if we know how to fix this length modifier.
- llvm::Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier();
+ Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier();
if (FixedLM) {
EmitFormatDiagnostic(S.PDiag(DiagID) << LM.toString() << CS.toString(),
getLocationOfByte(LM.getStart()),
@@ -2099,7 +2113,7 @@ void CheckFormatHandler::HandleNonStandardLengthModifier(
CharSourceRange LMRange = getSpecifierRange(LM.getStart(), LM.getLength());
// See if we know how to fix this length modifier.
- llvm::Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier();
+ Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier();
if (FixedLM) {
EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard)
<< LM.toString() << 0,
@@ -2126,7 +2140,7 @@ void CheckFormatHandler::HandleNonStandardConversionSpecifier(
using namespace analyze_format_string;
// See if we know how to fix this conversion specifier.
- llvm::Optional<ConversionSpecifier> FixedCS = CS.getStandardSpecifier();
+ Optional<ConversionSpecifier> FixedCS = CS.getStandardSpecifier();
if (FixedCS) {
EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard)
<< CS.toString() << /*conversion specifier*/1,
@@ -2346,11 +2360,11 @@ public:
const Expr *origFormatExpr, unsigned firstDataArg,
unsigned numDataArgs, bool isObjC,
const char *beg, bool hasVAListArg,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<const Expr *> Args,
unsigned formatIdx, bool inFunctionCall,
Sema::VariadicCallType CallType)
: CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
- numDataArgs, beg, hasVAListArg, Args, NumArgs,
+ numDataArgs, beg, hasVAListArg, Args,
formatIdx, inFunctionCall, CallType), ObjCContext(isObjC)
{}
@@ -2690,12 +2704,24 @@ static bool requiresParensToAddCast(const Expr *E) {
switch (Inside->getStmtClass()) {
case Stmt::ArraySubscriptExprClass:
case Stmt::CallExprClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::CXXBoolLiteralExprClass:
case Stmt::DeclRefExprClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::IntegerLiteralClass:
case Stmt::MemberExprClass:
+ case Stmt::ObjCArrayLiteralClass:
+ case Stmt::ObjCBoolLiteralExprClass:
+ case Stmt::ObjCBoxedExprClass:
+ case Stmt::ObjCDictionaryLiteralClass:
+ case Stmt::ObjCEncodeExprClass:
case Stmt::ObjCIvarRefExprClass:
case Stmt::ObjCMessageExprClass:
case Stmt::ObjCPropertyRefExprClass:
+ case Stmt::ObjCStringLiteralClass:
+ case Stmt::ObjCSubscriptRefExprClass:
case Stmt::ParenExprClass:
+ case Stmt::StringLiteralClass:
case Stmt::UnaryOperatorClass:
return false;
default:
@@ -2717,8 +2743,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
if (!AT.isValid())
return true;
- QualType IntendedTy = E->getType();
- if (AT.matchesType(S.Context, IntendedTy))
+ QualType ExprTy = E->getType();
+ if (AT.matchesType(S.Context, ExprTy))
return true;
// Look through argument promotions for our error message's reported type.
@@ -2729,7 +2755,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
if (ICE->getCastKind() == CK_IntegralCast ||
ICE->getCastKind() == CK_FloatingCast) {
E = ICE->getSubExpr();
- IntendedTy = E->getType();
+ ExprTy = E->getType();
// Check if we didn't match because of an implicit cast from a 'char'
// or 'short' to an 'int'. This is done because printf is a varargs
@@ -2737,22 +2763,63 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
if (ICE->getType() == S.Context.IntTy ||
ICE->getType() == S.Context.UnsignedIntTy) {
// All further checking is done on the subexpression.
- if (AT.matchesType(S.Context, IntendedTy))
+ if (AT.matchesType(S.Context, ExprTy))
return true;
}
}
+ } else if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) {
+ // Special case for 'a', which has type 'int' in C.
+ // Note, however, that we do /not/ want to treat multibyte constants like
+ // 'MooV' as characters! This form is deprecated but still exists.
+ if (ExprTy == S.Context.IntTy)
+ if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue()))
+ ExprTy = S.Context.CharTy;
+ }
+
+ // %C in an Objective-C context prints a unichar, not a wchar_t.
+ // If the argument is an integer of some kind, believe the %C and suggest
+ // a cast instead of changing the conversion specifier.
+ QualType IntendedTy = ExprTy;
+ if (ObjCContext &&
+ FS.getConversionSpecifier().getKind() == ConversionSpecifier::CArg) {
+ if (ExprTy->isIntegralOrUnscopedEnumerationType() &&
+ !ExprTy->isCharType()) {
+ // 'unichar' is defined as a typedef of unsigned short, but we should
+ // prefer using the typedef if it is visible.
+ IntendedTy = S.Context.UnsignedShortTy;
+
+ LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getLocStart(),
+ Sema::LookupOrdinaryName);
+ if (S.LookupName(Result, S.getCurScope())) {
+ NamedDecl *ND = Result.getFoundDecl();
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND))
+ if (TD->getUnderlyingType() == IntendedTy)
+ IntendedTy = S.Context.getTypedefType(TD);
+ }
+ }
}
+ // Special-case some of Darwin's platform-independence types by suggesting
+ // casts to primitive types that are known to be large enough.
+ bool ShouldNotPrintDirectly = false;
if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
- // Special-case some of Darwin's platform-independence types.
- if (const TypedefType *UserTy = IntendedTy->getAs<TypedefType>()) {
+ // Use a 'while' to peel off layers of typedefs.
+ QualType TyTy = IntendedTy;
+ while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) {
StringRef Name = UserTy->getDecl()->getName();
- IntendedTy = llvm::StringSwitch<QualType>(Name)
+ QualType CastTy = llvm::StringSwitch<QualType>(Name)
.Case("NSInteger", S.Context.LongTy)
.Case("NSUInteger", S.Context.UnsignedLongTy)
.Case("SInt32", S.Context.IntTy)
.Case("UInt32", S.Context.UnsignedIntTy)
- .Default(IntendedTy);
+ .Default(QualType());
+
+ if (!CastTy.isNull()) {
+ ShouldNotPrintDirectly = true;
+ IntendedTy = CastTy;
+ break;
+ }
+ TyTy = UserTy->desugar();
}
}
@@ -2769,7 +2836,19 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
- if (IntendedTy != E->getType()) {
+ if (IntendedTy == ExprTy) {
+ // In this case, the specifier is wrong and should be changed to match
+ // the argument.
+ EmitFormatDiagnostic(
+ S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << IntendedTy
+ << E->getSourceRange(),
+ E->getLocStart(),
+ /*IsStringLocation*/false,
+ SpecRange,
+ FixItHint::CreateReplacement(SpecRange, os.str()));
+
+ } else {
// The canonical type for formatting this value is different from the
// actual type of the expression. (This occurs, for example, with Darwin's
// NSInteger on 32-bit platforms, where it is typedef'd as 'int', but
@@ -2807,26 +2886,28 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
Hints.push_back(FixItHint::CreateInsertion(After, ")"));
}
- // We extract the name from the typedef because we don't want to show
- // the underlying type in the diagnostic.
- const TypedefType *UserTy = cast<TypedefType>(E->getType());
- StringRef Name = UserTy->getDecl()->getName();
-
- // Finally, emit the diagnostic.
- EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast)
- << Name << IntendedTy
- << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation=*/false,
- SpecRange, Hints);
- } else {
- EmitFormatDiagnostic(
- S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << IntendedTy
- << E->getSourceRange(),
- E->getLocStart(),
- /*IsStringLocation*/false,
- SpecRange,
- FixItHint::CreateReplacement(SpecRange, os.str()));
+ if (ShouldNotPrintDirectly) {
+ // The expression has a type that should not be printed directly.
+ // We extract the name from the typedef because we don't want to show
+ // the underlying type in the diagnostic.
+ StringRef Name = cast<TypedefType>(ExprTy)->getDecl()->getName();
+
+ EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast)
+ << Name << IntendedTy
+ << E->getSourceRange(),
+ E->getLocStart(), /*IsStringLocation=*/false,
+ SpecRange, Hints);
+ } else {
+ // In this case, the expression could be printed using a different
+ // specifier, but we've decided that the specifier is probably correct
+ // and we should cast instead. Just use the normal warning message.
+ EmitFormatDiagnostic(
+ S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << ExprTy
+ << E->getSourceRange(),
+ E->getLocStart(), /*IsStringLocation*/false,
+ SpecRange, Hints);
+ }
}
} else {
const CharSourceRange &CSR = getSpecifierRange(StartSpecifier,
@@ -2834,17 +2915,17 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// Since the warning for passing non-POD types to variadic functions
// was deferred until now, we emit a warning for non-POD
// arguments here.
- if (S.isValidVarArgType(E->getType()) == Sema::VAK_Invalid) {
+ if (S.isValidVarArgType(ExprTy) == Sema::VAK_Invalid) {
unsigned DiagKind;
- if (E->getType()->isObjCObjectType())
+ if (ExprTy->isObjCObjectType())
DiagKind = diag::err_cannot_pass_objc_interface_to_vararg_format;
else
DiagKind = diag::warn_non_pod_vararg_with_format_string;
EmitFormatDiagnostic(
S.PDiag(DiagKind)
- << S.getLangOpts().CPlusPlus0x
- << E->getType()
+ << S.getLangOpts().CPlusPlus11
+ << ExprTy
<< CallType
<< AT.getRepresentativeTypeName(S.Context)
<< CSR
@@ -2855,7 +2936,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
} else
EmitFormatDiagnostic(
S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << E->getType()
+ << AT.getRepresentativeTypeName(S.Context) << ExprTy
<< CSR
<< E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/false, CSR);
@@ -2872,12 +2953,12 @@ public:
CheckScanfHandler(Sema &s, const StringLiteral *fexpr,
const Expr *origFormatExpr, unsigned firstDataArg,
unsigned numDataArgs, const char *beg, bool hasVAListArg,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<const Expr *> Args,
unsigned formatIdx, bool inFunctionCall,
Sema::VariadicCallType CallType)
: CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
numDataArgs, beg, hasVAListArg,
- Args, NumArgs, formatIdx, inFunctionCall, CallType)
+ Args, formatIdx, inFunctionCall, CallType)
{}
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
@@ -3029,7 +3110,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
void Sema::CheckFormatString(const StringLiteral *FExpr,
const Expr *OrigFormatExpr,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<const Expr *> Args,
bool HasVAListArg, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
bool inFunctionCall, VariadicCallType CallType) {
@@ -3047,7 +3128,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
StringRef StrRef = FExpr->getString();
const char *Str = StrRef.data();
unsigned StrLen = StrRef.size();
- const unsigned numDataArgs = NumArgs - firstDataArg;
+ const unsigned numDataArgs = Args.size() - firstDataArg;
// CHECK: empty format string?
if (StrLen == 0 && numDataArgs > 0) {
@@ -3061,7 +3142,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
if (Type == FST_Printf || Type == FST_NSString) {
CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
numDataArgs, (Type == FST_NSString),
- Str, HasVAListArg, Args, NumArgs, format_idx,
+ Str, HasVAListArg, Args, format_idx,
inFunctionCall, CallType);
if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
@@ -3070,7 +3151,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
H.DoneProcessing();
} else if (Type == FST_Scanf) {
CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs,
- Str, HasVAListArg, Args, NumArgs, format_idx,
+ Str, HasVAListArg, Args, format_idx,
inFunctionCall, CallType);
if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen,
@@ -3177,7 +3258,8 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
if (const UnaryOperator *UnaryOp = dyn_cast<UnaryOperator>(Dest))
if (UnaryOp->getOpcode() == UO_AddrOf)
ActionIdx = 1; // If its an address-of operator, just remove it.
- if (Context.getTypeSize(PointeeTy) == Context.getCharWidth())
+ if (!PointeeTy->isIncompleteType() &&
+ (Context.getTypeSize(PointeeTy) == Context.getCharWidth()))
ActionIdx = 2; // If the pointee's size is sizeof(char),
// suggest an explicit length.
@@ -3922,7 +4004,11 @@ struct IntRange {
unsigned NumPositive = Enum->getNumPositiveBits();
unsigned NumNegative = Enum->getNumNegativeBits();
- return IntRange(std::max(NumPositive, NumNegative), NumNegative == 0);
+ if (NumNegative == 0)
+ return IntRange(NumPositive, true/*NonNegative*/);
+ else
+ return IntRange(std::max(NumPositive + 1, NumNegative),
+ false/*NonNegative*/);
}
const BuiltinType *BT = cast<BuiltinType>(T);
@@ -4328,38 +4414,108 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
Expr *Constant, Expr *Other,
llvm::APSInt Value,
bool RhsConstant) {
+ // 0 values are handled later by CheckTrivialUnsignedComparison().
+ if (Value == 0)
+ return;
+
BinaryOperatorKind op = E->getOpcode();
QualType OtherT = Other->getType();
QualType ConstantT = Constant->getType();
+ QualType CommonT = E->getLHS()->getType();
if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
return;
assert((OtherT->isIntegerType() && ConstantT->isIntegerType())
&& "comparison with non-integer type");
- // FIXME. handle cases for signedness to catch (signed char)N == 200
+
+ bool ConstantSigned = ConstantT->isSignedIntegerType();
+ bool CommonSigned = CommonT->isSignedIntegerType();
+
+ bool EqualityOnly = false;
+
+ // TODO: Investigate using GetExprRange() to get tighter bounds on
+ // on the bit ranges.
IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
- IntRange LitRange = GetValueRange(S.Context, Value, Value.getBitWidth());
- if (OtherRange.Width >= LitRange.Width)
- return;
+ unsigned OtherWidth = OtherRange.Width;
+
+ if (CommonSigned) {
+ // The common type is signed, therefore no signed to unsigned conversion.
+ if (!OtherRange.NonNegative) {
+ // Check that the constant is representable in type OtherT.
+ if (ConstantSigned) {
+ if (OtherWidth >= Value.getMinSignedBits())
+ return;
+ } else { // !ConstantSigned
+ if (OtherWidth >= Value.getActiveBits() + 1)
+ return;
+ }
+ } else { // !OtherSigned
+ // Check that the constant is representable in type OtherT.
+ // Negative values are out of range.
+ if (ConstantSigned) {
+ if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
+ return;
+ } else { // !ConstantSigned
+ if (OtherWidth >= Value.getActiveBits())
+ return;
+ }
+ }
+ } else { // !CommonSigned
+ if (OtherRange.NonNegative) {
+ if (OtherWidth >= Value.getActiveBits())
+ return;
+ } else if (!OtherRange.NonNegative && !ConstantSigned) {
+ // Check to see if the constant is representable in OtherT.
+ if (OtherWidth > Value.getActiveBits())
+ return;
+ // Check to see if the constant is equivalent to a negative value
+ // cast to CommonT.
+ if (S.Context.getIntWidth(ConstantT) == S.Context.getIntWidth(CommonT) &&
+ Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
+ return;
+ // The constant value rests between values that OtherT can represent after
+ // conversion. Relational comparison still works, but equality
+ // comparisons will be tautological.
+ EqualityOnly = true;
+ } else { // OtherSigned && ConstantSigned
+ assert(0 && "Two signed types converted to unsigned types.");
+ }
+ }
+
+ bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
+
bool IsTrue = true;
- if (op == BO_EQ)
- IsTrue = false;
- else if (op == BO_NE)
- IsTrue = true;
- else if (RhsConstant) {
+ if (op == BO_EQ || op == BO_NE) {
+ IsTrue = op == BO_NE;
+ } else if (EqualityOnly) {
+ return;
+ } else if (RhsConstant) {
if (op == BO_GT || op == BO_GE)
- IsTrue = !LitRange.NonNegative;
+ IsTrue = !PositiveConstant;
else // op == BO_LT || op == BO_LE
- IsTrue = LitRange.NonNegative;
+ IsTrue = PositiveConstant;
} else {
if (op == BO_LT || op == BO_LE)
- IsTrue = !LitRange.NonNegative;
+ IsTrue = !PositiveConstant;
else // op == BO_GT || op == BO_GE
- IsTrue = LitRange.NonNegative;
+ IsTrue = PositiveConstant;
}
- SmallString<16> PrettySourceValue(Value.toString(10));
+
+ // If this is a comparison to an enum constant, include that
+ // constant in the diagnostic.
+ const EnumConstantDecl *ED = 0;
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Constant))
+ ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
+
+ SmallString<64> PrettySourceValue;
+ llvm::raw_svector_ostream OS(PrettySourceValue);
+ if (ED)
+ OS << '\'' << *ED << "' (" << Value << ")";
+ else
+ OS << Value;
+
S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare)
- << PrettySourceValue << OtherT << IsTrue
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ << OS.str() << OtherT << IsTrue
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
}
/// Analyze the operands of the given comparison. Implements the
@@ -4800,7 +4956,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)
== Expr::NPCK_GNUNull) && !Target->isAnyPointerType()
&& !Target->isBlockPointerType() && !Target->isMemberPointerType()
- && Target->isScalarType()) {
+ && Target->isScalarType() && !Target->isNullPtrType()) {
SourceLocation Loc = E->getSourceRange().getBegin();
if (Loc.isMacroID())
Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
@@ -4843,7 +4999,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// People want to build with -Wshorten-64-to-32 and not -Wconversion.
if (S.SourceMgr.isInSystemMacro(CC))
return;
-
+
if (TargetRange.Width == 32 && S.Context.getIntWidth(E->getType()) == 64)
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32,
/* pruneControlFlow */ true);
@@ -4887,10 +5043,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (const EnumType *SourceEnum = Source->getAs<EnumType>())
if (const EnumType *TargetEnum = Target->getAs<EnumType>())
- if ((SourceEnum->getDecl()->getIdentifier() ||
- SourceEnum->getDecl()->getTypedefNameForAnonDecl()) &&
- (TargetEnum->getDecl()->getIdentifier() ||
- TargetEnum->getDecl()->getTypedefNameForAnonDecl()) &&
+ if (SourceEnum->getDecl()->hasNameForLinkage() &&
+ TargetEnum->getDecl()->hasNameForLinkage() &&
SourceEnum != TargetEnum) {
if (S.SourceMgr.isInSystemMacro(CC))
return;
@@ -5046,6 +5200,462 @@ void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) {
AnalyzeImplicitConversions(*this, E, CC);
}
+/// Diagnose when expression is an integer constant expression and its evaluation
+/// results in integer overflow
+void Sema::CheckForIntOverflow (Expr *E) {
+ if (isa<BinaryOperator>(E->IgnoreParens())) {
+ llvm::SmallVector<PartialDiagnosticAt, 4> Diags;
+ E->EvaluateForOverflow(Context, &Diags);
+ }
+}
+
+namespace {
+/// \brief Visitor for expressions which looks for unsequenced operations on the
+/// same object.
+class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
+ /// \brief A tree of sequenced regions within an expression. Two regions are
+ /// unsequenced if one is an ancestor or a descendent of the other. When we
+ /// finish processing an expression with sequencing, such as a comma
+ /// expression, we fold its tree nodes into its parent, since they are
+ /// unsequenced with respect to nodes we will visit later.
+ class SequenceTree {
+ struct Value {
+ explicit Value(unsigned Parent) : Parent(Parent), Merged(false) {}
+ unsigned Parent : 31;
+ bool Merged : 1;
+ };
+ llvm::SmallVector<Value, 8> Values;
+
+ public:
+ /// \brief A region within an expression which may be sequenced with respect
+ /// to some other region.
+ class Seq {
+ explicit Seq(unsigned N) : Index(N) {}
+ unsigned Index;
+ friend class SequenceTree;
+ public:
+ Seq() : Index(0) {}
+ };
+
+ SequenceTree() { Values.push_back(Value(0)); }
+ Seq root() const { return Seq(0); }
+
+ /// \brief Create a new sequence of operations, which is an unsequenced
+ /// subset of \p Parent. This sequence of operations is sequenced with
+ /// respect to other children of \p Parent.
+ Seq allocate(Seq Parent) {
+ Values.push_back(Value(Parent.Index));
+ return Seq(Values.size() - 1);
+ }
+
+ /// \brief Merge a sequence of operations into its parent.
+ void merge(Seq S) {
+ Values[S.Index].Merged = true;
+ }
+
+ /// \brief Determine whether two operations are unsequenced. This operation
+ /// is asymmetric: \p Cur should be the more recent sequence, and \p Old
+ /// should have been merged into its parent as appropriate.
+ bool isUnsequenced(Seq Cur, Seq Old) {
+ unsigned C = representative(Cur.Index);
+ unsigned Target = representative(Old.Index);
+ while (C >= Target) {
+ if (C == Target)
+ return true;
+ C = Values[C].Parent;
+ }
+ return false;
+ }
+
+ private:
+ /// \brief Pick a representative for a sequence.
+ unsigned representative(unsigned K) {
+ if (Values[K].Merged)
+ // Perform path compression as we go.
+ return Values[K].Parent = representative(Values[K].Parent);
+ return K;
+ }
+ };
+
+ /// An object for which we can track unsequenced uses.
+ typedef NamedDecl *Object;
+
+ /// Different flavors of object usage which we track. We only track the
+ /// least-sequenced usage of each kind.
+ enum UsageKind {
+ /// A read of an object. Multiple unsequenced reads are OK.
+ UK_Use,
+ /// A modification of an object which is sequenced before the value
+ /// computation of the expression, such as ++n.
+ UK_ModAsValue,
+ /// A modification of an object which is not sequenced before the value
+ /// computation of the expression, such as n++.
+ UK_ModAsSideEffect,
+
+ UK_Count = UK_ModAsSideEffect + 1
+ };
+
+ struct Usage {
+ Usage() : Use(0), Seq() {}
+ Expr *Use;
+ SequenceTree::Seq Seq;
+ };
+
+ struct UsageInfo {
+ UsageInfo() : Diagnosed(false) {}
+ Usage Uses[UK_Count];
+ /// Have we issued a diagnostic for this variable already?
+ bool Diagnosed;
+ };
+ typedef llvm::SmallDenseMap<Object, UsageInfo, 16> UsageInfoMap;
+
+ Sema &SemaRef;
+ /// Sequenced regions within the expression.
+ SequenceTree Tree;
+ /// Declaration modifications and references which we have seen.
+ UsageInfoMap UsageMap;
+ /// The region we are currently within.
+ SequenceTree::Seq Region;
+ /// Filled in with declarations which were modified as a side-effect
+ /// (that is, post-increment operations).
+ llvm::SmallVectorImpl<std::pair<Object, Usage> > *ModAsSideEffect;
+ /// Expressions to check later. We defer checking these to reduce
+ /// stack usage.
+ llvm::SmallVectorImpl<Expr*> &WorkList;
+
+ /// RAII object wrapping the visitation of a sequenced subexpression of an
+ /// expression. At the end of this process, the side-effects of the evaluation
+ /// become sequenced with respect to the value computation of the result, so
+ /// we downgrade any UK_ModAsSideEffect within the evaluation to
+ /// UK_ModAsValue.
+ struct SequencedSubexpression {
+ SequencedSubexpression(SequenceChecker &Self)
+ : Self(Self), OldModAsSideEffect(Self.ModAsSideEffect) {
+ Self.ModAsSideEffect = &ModAsSideEffect;
+ }
+ ~SequencedSubexpression() {
+ for (unsigned I = 0, E = ModAsSideEffect.size(); I != E; ++I) {
+ UsageInfo &U = Self.UsageMap[ModAsSideEffect[I].first];
+ U.Uses[UK_ModAsSideEffect] = ModAsSideEffect[I].second;
+ Self.addUsage(U, ModAsSideEffect[I].first,
+ ModAsSideEffect[I].second.Use, UK_ModAsValue);
+ }
+ Self.ModAsSideEffect = OldModAsSideEffect;
+ }
+
+ SequenceChecker &Self;
+ llvm::SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect;
+ llvm::SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect;
+ };
+
+ /// \brief Find the object which is produced by the specified expression,
+ /// if any.
+ Object getObject(Expr *E, bool Mod) const {
+ E = E->IgnoreParenCasts();
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ if (Mod && (UO->getOpcode() == UO_PreInc || UO->getOpcode() == UO_PreDec))
+ return getObject(UO->getSubExpr(), Mod);
+ } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Comma)
+ return getObject(BO->getRHS(), Mod);
+ if (Mod && BO->isAssignmentOp())
+ return getObject(BO->getLHS(), Mod);
+ } else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ // FIXME: Check for more interesting cases, like "x.n = ++x.n".
+ if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenCasts()))
+ return ME->getMemberDecl();
+ } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ // FIXME: If this is a reference, map through to its value.
+ return DRE->getDecl();
+ return 0;
+ }
+
+ /// \brief Note that an object was modified or used by an expression.
+ void addUsage(UsageInfo &UI, Object O, Expr *Ref, UsageKind UK) {
+ Usage &U = UI.Uses[UK];
+ if (!U.Use || !Tree.isUnsequenced(Region, U.Seq)) {
+ if (UK == UK_ModAsSideEffect && ModAsSideEffect)
+ ModAsSideEffect->push_back(std::make_pair(O, U));
+ U.Use = Ref;
+ U.Seq = Region;
+ }
+ }
+ /// \brief Check whether a modification or use conflicts with a prior usage.
+ void checkUsage(Object O, UsageInfo &UI, Expr *Ref, UsageKind OtherKind,
+ bool IsModMod) {
+ if (UI.Diagnosed)
+ return;
+
+ const Usage &U = UI.Uses[OtherKind];
+ if (!U.Use || !Tree.isUnsequenced(Region, U.Seq))
+ return;
+
+ Expr *Mod = U.Use;
+ Expr *ModOrUse = Ref;
+ if (OtherKind == UK_Use)
+ std::swap(Mod, ModOrUse);
+
+ SemaRef.Diag(Mod->getExprLoc(),
+ IsModMod ? diag::warn_unsequenced_mod_mod
+ : diag::warn_unsequenced_mod_use)
+ << O << SourceRange(ModOrUse->getExprLoc());
+ UI.Diagnosed = true;
+ }
+
+ void notePreUse(Object O, Expr *Use) {
+ UsageInfo &U = UsageMap[O];
+ // Uses conflict with other modifications.
+ checkUsage(O, U, Use, UK_ModAsValue, false);
+ }
+ void notePostUse(Object O, Expr *Use) {
+ UsageInfo &U = UsageMap[O];
+ checkUsage(O, U, Use, UK_ModAsSideEffect, false);
+ addUsage(U, O, Use, UK_Use);
+ }
+
+ void notePreMod(Object O, Expr *Mod) {
+ UsageInfo &U = UsageMap[O];
+ // Modifications conflict with other modifications and with uses.
+ checkUsage(O, U, Mod, UK_ModAsValue, true);
+ checkUsage(O, U, Mod, UK_Use, false);
+ }
+ void notePostMod(Object O, Expr *Use, UsageKind UK) {
+ UsageInfo &U = UsageMap[O];
+ checkUsage(O, U, Use, UK_ModAsSideEffect, true);
+ addUsage(U, O, Use, UK);
+ }
+
+public:
+ SequenceChecker(Sema &S, Expr *E,
+ llvm::SmallVectorImpl<Expr*> &WorkList)
+ : EvaluatedExprVisitor<SequenceChecker>(S.Context), SemaRef(S),
+ Region(Tree.root()), ModAsSideEffect(0), WorkList(WorkList) {
+ Visit(E);
+ }
+
+ void VisitStmt(Stmt *S) {
+ // Skip all statements which aren't expressions for now.
+ }
+
+ void VisitExpr(Expr *E) {
+ // By default, just recurse to evaluated subexpressions.
+ EvaluatedExprVisitor<SequenceChecker>::VisitStmt(E);
+ }
+
+ void VisitCastExpr(CastExpr *E) {
+ Object O = Object();
+ if (E->getCastKind() == CK_LValueToRValue)
+ O = getObject(E->getSubExpr(), false);
+
+ if (O)
+ notePreUse(O, E);
+ VisitExpr(E);
+ if (O)
+ notePostUse(O, E);
+ }
+
+ void VisitBinComma(BinaryOperator *BO) {
+ // C++11 [expr.comma]p1:
+ // Every value computation and side effect associated with the left
+ // expression is sequenced before every value computation and side
+ // effect associated with the right expression.
+ SequenceTree::Seq LHS = Tree.allocate(Region);
+ SequenceTree::Seq RHS = Tree.allocate(Region);
+ SequenceTree::Seq OldRegion = Region;
+
+ {
+ SequencedSubexpression SeqLHS(*this);
+ Region = LHS;
+ Visit(BO->getLHS());
+ }
+
+ Region = RHS;
+ Visit(BO->getRHS());
+
+ Region = OldRegion;
+
+ // Forget that LHS and RHS are sequenced. They are both unsequenced
+ // with respect to other stuff.
+ Tree.merge(LHS);
+ Tree.merge(RHS);
+ }
+
+ void VisitBinAssign(BinaryOperator *BO) {
+ // The modification is sequenced after the value computation of the LHS
+ // and RHS, so check it before inspecting the operands and update the
+ // map afterwards.
+ Object O = getObject(BO->getLHS(), true);
+ if (!O)
+ return VisitExpr(BO);
+
+ notePreMod(O, BO);
+
+ // C++11 [expr.ass]p7:
+ // E1 op= E2 is equivalent to E1 = E1 op E2, except that E1 is evaluated
+ // only once.
+ //
+ // Therefore, for a compound assignment operator, O is considered used
+ // everywhere except within the evaluation of E1 itself.
+ if (isa<CompoundAssignOperator>(BO))
+ notePreUse(O, BO);
+
+ Visit(BO->getLHS());
+
+ if (isa<CompoundAssignOperator>(BO))
+ notePostUse(O, BO);
+
+ Visit(BO->getRHS());
+
+ notePostMod(O, BO, UK_ModAsValue);
+ }
+ void VisitCompoundAssignOperator(CompoundAssignOperator *CAO) {
+ VisitBinAssign(CAO);
+ }
+
+ void VisitUnaryPreInc(UnaryOperator *UO) { VisitUnaryPreIncDec(UO); }
+ void VisitUnaryPreDec(UnaryOperator *UO) { VisitUnaryPreIncDec(UO); }
+ void VisitUnaryPreIncDec(UnaryOperator *UO) {
+ Object O = getObject(UO->getSubExpr(), true);
+ if (!O)
+ return VisitExpr(UO);
+
+ notePreMod(O, UO);
+ Visit(UO->getSubExpr());
+ notePostMod(O, UO, UK_ModAsValue);
+ }
+
+ void VisitUnaryPostInc(UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
+ void VisitUnaryPostDec(UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
+ void VisitUnaryPostIncDec(UnaryOperator *UO) {
+ Object O = getObject(UO->getSubExpr(), true);
+ if (!O)
+ return VisitExpr(UO);
+
+ notePreMod(O, UO);
+ Visit(UO->getSubExpr());
+ notePostMod(O, UO, UK_ModAsSideEffect);
+ }
+
+ /// Don't visit the RHS of '&&' or '||' if it might not be evaluated.
+ void VisitBinLOr(BinaryOperator *BO) {
+ // The side-effects of the LHS of an '&&' are sequenced before the
+ // value computation of the RHS, and hence before the value computation
+ // of the '&&' itself, unless the LHS evaluates to zero. We treat them
+ // as if they were unconditionally sequenced.
+ {
+ SequencedSubexpression Sequenced(*this);
+ Visit(BO->getLHS());
+ }
+
+ bool Result;
+ if (!BO->getLHS()->isValueDependent() &&
+ BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) {
+ if (!Result)
+ Visit(BO->getRHS());
+ } else {
+ // Check for unsequenced operations in the RHS, treating it as an
+ // entirely separate evaluation.
+ //
+ // FIXME: If there are operations in the RHS which are unsequenced
+ // with respect to operations outside the RHS, and those operations
+ // are unconditionally evaluated, diagnose them.
+ WorkList.push_back(BO->getRHS());
+ }
+ }
+ void VisitBinLAnd(BinaryOperator *BO) {
+ {
+ SequencedSubexpression Sequenced(*this);
+ Visit(BO->getLHS());
+ }
+
+ bool Result;
+ if (!BO->getLHS()->isValueDependent() &&
+ BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) {
+ if (Result)
+ Visit(BO->getRHS());
+ } else {
+ WorkList.push_back(BO->getRHS());
+ }
+ }
+
+ // Only visit the condition, unless we can be sure which subexpression will
+ // be chosen.
+ void VisitAbstractConditionalOperator(AbstractConditionalOperator *CO) {
+ SequencedSubexpression Sequenced(*this);
+ Visit(CO->getCond());
+
+ bool Result;
+ if (!CO->getCond()->isValueDependent() &&
+ CO->getCond()->EvaluateAsBooleanCondition(Result, SemaRef.Context))
+ Visit(Result ? CO->getTrueExpr() : CO->getFalseExpr());
+ else {
+ WorkList.push_back(CO->getTrueExpr());
+ WorkList.push_back(CO->getFalseExpr());
+ }
+ }
+
+ void VisitCXXConstructExpr(CXXConstructExpr *CCE) {
+ if (!CCE->isListInitialization())
+ return VisitExpr(CCE);
+
+ // In C++11, list initializations are sequenced.
+ llvm::SmallVector<SequenceTree::Seq, 32> Elts;
+ SequenceTree::Seq Parent = Region;
+ for (CXXConstructExpr::arg_iterator I = CCE->arg_begin(),
+ E = CCE->arg_end();
+ I != E; ++I) {
+ Region = Tree.allocate(Parent);
+ Elts.push_back(Region);
+ Visit(*I);
+ }
+
+ // Forget that the initializers are sequenced.
+ Region = Parent;
+ for (unsigned I = 0; I < Elts.size(); ++I)
+ Tree.merge(Elts[I]);
+ }
+
+ void VisitInitListExpr(InitListExpr *ILE) {
+ if (!SemaRef.getLangOpts().CPlusPlus11)
+ return VisitExpr(ILE);
+
+ // In C++11, list initializations are sequenced.
+ llvm::SmallVector<SequenceTree::Seq, 32> Elts;
+ SequenceTree::Seq Parent = Region;
+ for (unsigned I = 0; I < ILE->getNumInits(); ++I) {
+ Expr *E = ILE->getInit(I);
+ if (!E) continue;
+ Region = Tree.allocate(Parent);
+ Elts.push_back(Region);
+ Visit(E);
+ }
+
+ // Forget that the initializers are sequenced.
+ Region = Parent;
+ for (unsigned I = 0; I < Elts.size(); ++I)
+ Tree.merge(Elts[I]);
+ }
+};
+}
+
+void Sema::CheckUnsequencedOperations(Expr *E) {
+ llvm::SmallVector<Expr*, 8> WorkList;
+ WorkList.push_back(E);
+ while (!WorkList.empty()) {
+ Expr *Item = WorkList.back();
+ WorkList.pop_back();
+ SequenceChecker(*this, Item, WorkList);
+ }
+}
+
+void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc,
+ bool IsConstexpr) {
+ CheckImplicitConversions(E, CheckLoc);
+ CheckUnsequencedOperations(E);
+ if (!IsConstexpr && !E->isValueDependent())
+ CheckForIntOverflow(E);
+}
+
void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
FieldDecl *BitField,
Expr *Init) {
@@ -5091,7 +5701,7 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd,
QualType PType = Param->getOriginalType();
if (const ArrayType *AT = Context.getAsArrayType(PType)) {
if (AT->getSizeModifier() == ArrayType::Star) {
- // FIXME: This diagnosic should point the '[*]' if source-location
+ // FIXME: This diagnostic should point the '[*]' if source-location
// information is added for it.
Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
}
@@ -5174,16 +5784,16 @@ static bool IsTailPaddedMemberArray(Sema &S, llvm::APInt Size,
while (TInfo) {
TypeLoc TL = TInfo->getTypeLoc();
// Look through typedefs.
- const TypedefTypeLoc *TTL = dyn_cast<TypedefTypeLoc>(&TL);
- if (TTL) {
- const TypedefNameDecl *TDL = TTL->getTypedefNameDecl();
+ if (TypedefTypeLoc TTL = TL.getAs<TypedefTypeLoc>()) {
+ const TypedefNameDecl *TDL = TTL.getTypedefNameDecl();
TInfo = TDL->getTypeSourceInfo();
continue;
}
- ConstantArrayTypeLoc CTL = cast<ConstantArrayTypeLoc>(TL);
- const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr());
- if (!SizeExpr || SizeExpr->getExprLoc().isMacroID())
- return false;
+ if (ConstantArrayTypeLoc CTL = TL.getAs<ConstantArrayTypeLoc>()) {
+ const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr());
+ if (!SizeExpr || SizeExpr->getExprLoc().isMacroID())
+ return false;
+ }
break;
}
@@ -5574,7 +6184,7 @@ static bool isSetterLikeSelector(Selector sel) {
return false;
if (str.empty()) return true;
- return !islower(str.front());
+ return !isLowercase(str.front());
}
/// Check a message send to see if it's likely to cause a retain cycle.
@@ -5625,21 +6235,59 @@ void Sema::checkRetainCycles(VarDecl *Var, Expr *Init) {
diagnoseRetainCycle(*this, Capturer, Owner);
}
-bool Sema::checkUnsafeAssigns(SourceLocation Loc,
- QualType LHS, Expr *RHS) {
- Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
- if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
+static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc,
+ Expr *RHS, bool isProperty) {
+ // Check if RHS is an Objective-C object literal, which also can get
+ // immediately zapped in a weak reference. Note that we explicitly
+ // allow ObjCStringLiterals, since those are designed to never really die.
+ RHS = RHS->IgnoreParenImpCasts();
+
+ // This enum needs to match with the 'select' in
+ // warn_objc_arc_literal_assign (off-by-1).
+ Sema::ObjCLiteralKind Kind = S.CheckLiteralKind(RHS);
+ if (Kind == Sema::LK_String || Kind == Sema::LK_None)
return false;
- // strip off any implicit cast added to get to the one arc-specific
+
+ S.Diag(Loc, diag::warn_arc_literal_assign)
+ << (unsigned) Kind
+ << (isProperty ? 0 : 1)
+ << RHS->getSourceRange();
+
+ return true;
+}
+
+static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc,
+ Qualifiers::ObjCLifetime LT,
+ Expr *RHS, bool isProperty) {
+ // Strip off any implicit cast added to get to the one ARC-specific.
while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
if (cast->getCastKind() == CK_ARCConsumeObject) {
- Diag(Loc, diag::warn_arc_retained_assign)
- << (LT == Qualifiers::OCL_ExplicitNone) << 1
+ S.Diag(Loc, diag::warn_arc_retained_assign)
+ << (LT == Qualifiers::OCL_ExplicitNone)
+ << (isProperty ? 0 : 1)
<< RHS->getSourceRange();
return true;
}
RHS = cast->getSubExpr();
}
+
+ if (LT == Qualifiers::OCL_Weak &&
+ checkUnsafeAssignLiteral(S, Loc, RHS, isProperty))
+ return true;
+
+ return false;
+}
+
+bool Sema::checkUnsafeAssigns(SourceLocation Loc,
+ QualType LHS, Expr *RHS) {
+ Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
+
+ if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
+ return false;
+
+ if (checkUnsafeAssignObject(*this, Loc, LT, RHS, false))
+ return true;
+
return false;
}
@@ -5702,14 +6350,8 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
}
}
else if (Attributes & ObjCPropertyDecl::OBJC_PR_weak) {
- while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
- if (cast->getCastKind() == CK_ARCConsumeObject) {
- Diag(Loc, diag::warn_arc_retained_assign)
- << 0 << 0<< RHS->getSourceRange();
- return;
- }
- RHS = cast->getSubExpr();
- }
+ if (checkUnsafeAssignObject(*this, Loc, Qualifiers::OCL_Weak, RHS, true))
+ return;
}
}
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index b1aead8f026d..2db1e2afa26b 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -11,18 +11,19 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Overload.h"
-#include "clang/Sema/CodeCompleteConsumer.h"
-#include "clang/Sema/ExternalSemaSource.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Overload.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -45,7 +46,7 @@ namespace {
/// name-lookup routines to specify which declarations should be included in
/// the result set (when it returns true) and which declarations should be
/// filtered out (returns false).
- typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
+ typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
typedef CodeCompletionResult Result;
@@ -56,9 +57,9 @@ namespace {
/// \brief A record of all of the declarations we have found and placed
/// into the result set, used to ensure that no declaration ever gets into
/// the result set twice.
- llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
+ llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
- typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
+ typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
/// \brief An entry in the shadow map, which is optimized to store
/// a single (declaration, index) mapping (the common case) but
@@ -68,7 +69,7 @@ namespace {
/// \brief Contains either the solitary NamedDecl * or a vector
/// of (declaration, index) pairs.
- llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
+ llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
/// \brief When the entry contains a single declaration, this is
/// the index associated with that entry.
@@ -77,7 +78,7 @@ namespace {
public:
ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
- void Add(NamedDecl *ND, unsigned Index) {
+ void Add(const NamedDecl *ND, unsigned Index) {
if (DeclOrVector.isNull()) {
// 0 - > 1 elements: just set the single element information.
DeclOrVector = ND;
@@ -85,7 +86,8 @@ namespace {
return;
}
- if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
+ if (const NamedDecl *PrevND =
+ DeclOrVector.dyn_cast<const NamedDecl *>()) {
// 1 -> 2 elements: create the vector of results and push in the
// existing declaration.
DeclIndexPairVector *Vec = new DeclIndexPairVector;
@@ -161,7 +163,7 @@ namespace {
/// \brief If we are in an instance method definition, the \@implementation
/// object.
ObjCImplementationDecl *ObjCImplementation;
-
+
void AdjustResultPriorityForDecl(Result &R);
void MaybeAddConstructorResults(Result R);
@@ -195,7 +197,10 @@ namespace {
break;
}
}
-
+
+ /// \brief Determine the priority for a reference to the given declaration.
+ unsigned getBasePriority(const NamedDecl *D);
+
/// \brief Whether we should include code patterns in the completion
/// results.
bool includeCodePatterns() const {
@@ -265,7 +270,8 @@ namespace {
///
/// \param AsNestedNameSpecifier will be set true if this declaration is
/// only interesting when it is a nested-name-specifier.
- bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
+ bool isInterestingDecl(const NamedDecl *ND,
+ bool &AsNestedNameSpecifier) const;
/// \brief Check whether the result is hidden by the Hiding declaration.
///
@@ -274,7 +280,7 @@ namespace {
/// modified to describe how the result can be found (e.g., via extra
/// qualification).
bool CheckHiddenResult(Result &R, DeclContext *CurContext,
- NamedDecl *Hiding);
+ const NamedDecl *Hiding);
/// \brief Add a new result to this result set (if it isn't already in one
/// of the shadow maps), or replace an existing result (for, e.g., a
@@ -309,7 +315,7 @@ namespace {
void ExitScope();
/// \brief Ignore this declaration, if it is seen again.
- void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
+ void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
/// \name Name lookup predicates
///
@@ -317,29 +323,29 @@ namespace {
/// results of name lookup. All of the predicates have the same type, so that
///
//@{
- bool IsOrdinaryName(NamedDecl *ND) const;
- bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
- bool IsIntegralConstantValue(NamedDecl *ND) const;
- bool IsOrdinaryNonValueName(NamedDecl *ND) const;
- bool IsNestedNameSpecifier(NamedDecl *ND) const;
- bool IsEnum(NamedDecl *ND) const;
- bool IsClassOrStruct(NamedDecl *ND) const;
- bool IsUnion(NamedDecl *ND) const;
- bool IsNamespace(NamedDecl *ND) const;
- bool IsNamespaceOrAlias(NamedDecl *ND) const;
- bool IsType(NamedDecl *ND) const;
- bool IsMember(NamedDecl *ND) const;
- bool IsObjCIvar(NamedDecl *ND) const;
- bool IsObjCMessageReceiver(NamedDecl *ND) const;
- bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
- bool IsObjCCollection(NamedDecl *ND) const;
- bool IsImpossibleToSatisfy(NamedDecl *ND) const;
+ bool IsOrdinaryName(const NamedDecl *ND) const;
+ bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
+ bool IsIntegralConstantValue(const NamedDecl *ND) const;
+ bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
+ bool IsNestedNameSpecifier(const NamedDecl *ND) const;
+ bool IsEnum(const NamedDecl *ND) const;
+ bool IsClassOrStruct(const NamedDecl *ND) const;
+ bool IsUnion(const NamedDecl *ND) const;
+ bool IsNamespace(const NamedDecl *ND) const;
+ bool IsNamespaceOrAlias(const NamedDecl *ND) const;
+ bool IsType(const NamedDecl *ND) const;
+ bool IsMember(const NamedDecl *ND) const;
+ bool IsObjCIvar(const NamedDecl *ND) const;
+ bool IsObjCMessageReceiver(const NamedDecl *ND) const;
+ bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
+ bool IsObjCCollection(const NamedDecl *ND) const;
+ bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
//@}
};
}
class ResultBuilder::ShadowMapEntry::iterator {
- llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
+ llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
unsigned SingleDeclIndex;
public:
@@ -361,14 +367,14 @@ public:
iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
- iterator(NamedDecl *SingleDecl, unsigned Index)
+ iterator(const NamedDecl *SingleDecl, unsigned Index)
: DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
iterator(const DeclIndexPair *Iterator)
: DeclOrIterator(Iterator), SingleDeclIndex(0) { }
iterator &operator++() {
- if (DeclOrIterator.is<NamedDecl *>()) {
+ if (DeclOrIterator.is<const NamedDecl *>()) {
DeclOrIterator = (NamedDecl *)0;
SingleDeclIndex = 0;
return *this;
@@ -387,7 +393,7 @@ public:
}*/
reference operator*() const {
- if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
+ if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
return reference(ND, SingleDeclIndex);
return *DeclOrIterator.get<const DeclIndexPair*>();
@@ -413,7 +419,7 @@ ResultBuilder::ShadowMapEntry::begin() const {
if (DeclOrVector.isNull())
return iterator();
- if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
+ if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
return iterator(ND, SingleDeclIndex);
return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
@@ -421,7 +427,7 @@ ResultBuilder::ShadowMapEntry::begin() const {
ResultBuilder::ShadowMapEntry::iterator
ResultBuilder::ShadowMapEntry::end() const {
- if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
+ if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
return iterator();
return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
@@ -442,11 +448,11 @@ ResultBuilder::ShadowMapEntry::end() const {
/// NULL if no qualification is needed.
static NestedNameSpecifier *
getRequiredQualification(ASTContext &Context,
- DeclContext *CurContext,
- DeclContext *TargetContext) {
- SmallVector<DeclContext *, 4> TargetParents;
+ const DeclContext *CurContext,
+ const DeclContext *TargetContext) {
+ SmallVector<const DeclContext *, 4> TargetParents;
- for (DeclContext *CommonAncestor = TargetContext;
+ for (const DeclContext *CommonAncestor = TargetContext;
CommonAncestor && !CommonAncestor->Encloses(CurContext);
CommonAncestor = CommonAncestor->getLookupParent()) {
if (CommonAncestor->isTransparentContext() ||
@@ -458,16 +464,16 @@ getRequiredQualification(ASTContext &Context,
NestedNameSpecifier *Result = 0;
while (!TargetParents.empty()) {
- DeclContext *Parent = TargetParents.back();
+ const DeclContext *Parent = TargetParents.back();
TargetParents.pop_back();
- if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
+ if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
if (!Namespace->getIdentifier())
continue;
Result = NestedNameSpecifier::Create(Context, Result, Namespace);
}
- else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
+ else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Result = NestedNameSpecifier::Create(Context, Result,
false,
Context.getTypeDeclType(TD).getTypePtr());
@@ -475,7 +481,7 @@ getRequiredQualification(ASTContext &Context,
return Result;
}
-bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
+bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
bool &AsNestedNameSpecifier) const {
AsNestedNameSpecifier = false;
@@ -547,14 +553,15 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
}
bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
- NamedDecl *Hiding) {
+ const NamedDecl *Hiding) {
// In C, there is no way to refer to a hidden name.
// FIXME: This isn't true; we can find a tag name hidden by an ordinary
// name if we introduce the tag type.
if (!SemaRef.getLangOpts().CPlusPlus)
return true;
- DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
+ const DeclContext *HiddenCtx =
+ R.Declaration->getDeclContext()->getRedeclContext();
// There is no way to qualify a name declared in a function or method.
if (HiddenCtx->isFunctionOrMethod())
@@ -645,26 +652,27 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
/// \brief Get the type that a given expression will have if this declaration
/// is used as an expression in its "typical" code-completion form.
-QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
+QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
- if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+ if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
return C.getTypeDeclType(Type);
- if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
+ if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
return C.getObjCInterfaceType(Iface);
QualType T;
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
T = Function->getCallResultType();
- else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
T = Method->getSendResultType();
- else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ else if (const FunctionTemplateDecl *FunTmpl =
+ dyn_cast<FunctionTemplateDecl>(ND))
T = FunTmpl->getTemplatedDecl()->getCallResultType();
- else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
- else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+ else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
T = Property->getType();
- else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+ else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
T = Value->getType();
else
return QualType();
@@ -703,11 +711,48 @@ QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
return T;
}
+unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
+ if (!ND)
+ return CCP_Unlikely;
+
+ // Context-based decisions.
+ const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
+ if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
+ // _cmd is relatively rare
+ if (const ImplicitParamDecl *ImplicitParam =
+ dyn_cast<ImplicitParamDecl>(ND))
+ if (ImplicitParam->getIdentifier() &&
+ ImplicitParam->getIdentifier()->isStr("_cmd"))
+ return CCP_ObjC_cmd;
+
+ return CCP_LocalDeclaration;
+ }
+ if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
+ return CCP_MemberDeclaration;
+
+ // Content-based decisions.
+ if (isa<EnumConstantDecl>(ND))
+ return CCP_Constant;
+
+ // Use CCP_Type for type declarations unless we're in a statement, Objective-C
+ // message receiver, or parenthesized expression context. There, it's as
+ // likely that the user will want to write a type as other declarations.
+ if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
+ !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
+ CompletionContext.getKind()
+ == CodeCompletionContext::CCC_ObjCMessageReceiver ||
+ CompletionContext.getKind()
+ == CodeCompletionContext::CCC_ParenthesizedExpression))
+ return CCP_Type;
+
+ return CCP_Declaration;
+}
+
void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
// If this is an Objective-C method declaration whose selector matches our
// preferred selector, give it a priority boost.
if (!PreferredSelector.isNull())
- if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
+ if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
if (PreferredSelector == Method->getSelector())
R.Priority += CCD_SelectorMatch;
@@ -735,9 +780,9 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
return;
ASTContext &Context = SemaRef.Context;
- NamedDecl *D = R.Declaration;
- CXXRecordDecl *Record = 0;
- if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
+ const NamedDecl *D = R.Declaration;
+ const CXXRecordDecl *Record = 0;
+ if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Record = ClassTemplate->getTemplatedDecl();
else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
// Skip specializations and partial specializations.
@@ -757,9 +802,11 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(RecordTy));
- for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
- Ctors.first != Ctors.second; ++Ctors.first) {
- R.Declaration = *Ctors.first;
+ DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName);
+ for (DeclContext::lookup_const_iterator I = Ctors.begin(),
+ E = Ctors.end();
+ I != E; ++I) {
+ R.Declaration = *I;
R.CursorKind = getCursorKindForDecl(R.Declaration);
Results.push_back(R);
}
@@ -775,12 +822,16 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
}
// Look through using declarations.
- if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
- MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
+ if (const UsingShadowDecl *Using =
+ dyn_cast<UsingShadowDecl>(R.Declaration)) {
+ MaybeAddResult(Result(Using->getTargetDecl(),
+ getBasePriority(Using->getTargetDecl()),
+ R.Qualifier),
+ CurContext);
return;
}
- Decl *CanonDecl = R.Declaration->getCanonicalDecl();
+ const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
unsigned IDNS = CanonDecl->getIdentifierNamespace();
bool AsNestedNameSpecifier = false;
@@ -800,7 +851,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
}
for (; I != IEnd; ++I) {
- NamedDecl *ND = I->first;
+ const NamedDecl *ND = I->first;
unsigned Index = I->second;
if (ND->getCanonicalDecl() == CanonDecl) {
// This is a redeclaration. Always pick the newer declaration.
@@ -859,10 +910,10 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
- DeclContext *Ctx = R.Declaration->getDeclContext();
- if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+ const DeclContext *Ctx = R.Declaration->getDeclContext();
+ if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
- else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+ else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
@@ -887,8 +938,11 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
}
// Look through using declarations.
- if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
- AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
+ if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+ AddResult(Result(Using->getTargetDecl(),
+ getBasePriority(Using->getTargetDecl()),
+ R.Qualifier),
+ CurContext, Hiding);
return;
}
@@ -921,10 +975,10 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
- DeclContext *Ctx = R.Declaration->getDeclContext();
- if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+ const DeclContext *Ctx = R.Declaration->getDeclContext();
+ if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
- else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+ else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
@@ -938,7 +992,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
AdjustResultPriorityForDecl(R);
if (HasObjectTypeQualifiers)
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
if (Method->isInstance()) {
Qualifiers MethodQuals
= Qualifiers::fromCVRMask(Method->getTypeQualifiers());
@@ -982,7 +1036,7 @@ void ResultBuilder::ExitScope() {
/// \brief Determines whether this given declaration will be found by
/// ordinary name lookup.
-bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
+bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
unsigned IDNS = Decl::IDNS_Ordinary;
@@ -998,7 +1052,7 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
/// \brief Determines whether this given declaration will be found by
/// ordinary name lookup but is not a type name.
-bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
+bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
return false;
@@ -1014,11 +1068,11 @@ bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
return ND->getIdentifierNamespace() & IDNS;
}
-bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
+bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
if (!IsOrdinaryNonTypeName(ND))
return 0;
- if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
if (VD->getType()->isIntegralOrEnumerationType())
return true;
@@ -1027,7 +1081,7 @@ bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
/// \brief Determines whether this given declaration will be found by
/// ordinary name lookup.
-bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
+bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
unsigned IDNS = Decl::IDNS_Ordinary;
@@ -1041,27 +1095,27 @@ bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
/// \brief Determines whether the given declaration is suitable as the
/// start of a C++ nested-name-specifier, e.g., a class or namespace.
-bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
+bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
// Allow us to find class templates, too.
- if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
return SemaRef.isAcceptableNestedNameSpecifier(ND);
}
/// \brief Determines whether the given declaration is an enumeration.
-bool ResultBuilder::IsEnum(NamedDecl *ND) const {
+bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
return isa<EnumDecl>(ND);
}
/// \brief Determines whether the given declaration is a class or struct.
-bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
+bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
// Allow us to find class templates, too.
- if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
// For purposes of this check, interfaces match too.
- if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
return RD->getTagKind() == TTK_Class ||
RD->getTagKind() == TTK_Struct ||
RD->getTagKind() == TTK_Interface;
@@ -1070,31 +1124,31 @@ bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
}
/// \brief Determines whether the given declaration is a union.
-bool ResultBuilder::IsUnion(NamedDecl *ND) const {
+bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
// Allow us to find class templates, too.
- if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
- if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
return RD->getTagKind() == TTK_Union;
return false;
}
/// \brief Determines whether the given declaration is a namespace.
-bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
+bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
return isa<NamespaceDecl>(ND);
}
/// \brief Determines whether the given declaration is a namespace or
/// namespace alias.
-bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
+bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
}
/// \brief Determines whether the given declaration is a type.
-bool ResultBuilder::IsType(NamedDecl *ND) const {
- if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+bool ResultBuilder::IsType(const NamedDecl *ND) const {
+ if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
ND = Using->getTargetDecl();
return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
@@ -1103,8 +1157,8 @@ bool ResultBuilder::IsType(NamedDecl *ND) const {
/// \brief Determines which members of a class should be visible via
/// "." or "->". Only value declarations, nested name specifiers, and
/// using declarations thereof should show up.
-bool ResultBuilder::IsMember(NamedDecl *ND) const {
- if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+bool ResultBuilder::IsMember(const NamedDecl *ND) const {
+ if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
ND = Using->getTargetDecl();
return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
@@ -1144,7 +1198,7 @@ static bool isObjCReceiverType(ASTContext &C, QualType T) {
return T->isDependentType() || T->isRecordType();
}
-bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
+bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
QualType T = getDeclUsageType(SemaRef.Context, ND);
if (T.isNull())
return false;
@@ -1153,18 +1207,18 @@ bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
return isObjCReceiverType(SemaRef.Context, T);
}
-bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
+bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
if (IsObjCMessageReceiver(ND))
return true;
- VarDecl *Var = dyn_cast<VarDecl>(ND);
+ const VarDecl *Var = dyn_cast<VarDecl>(ND);
if (!Var)
return false;
return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
}
-bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
+bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
(!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
return false;
@@ -1179,13 +1233,13 @@ bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
(SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
}
-bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
+bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
return false;
}
/// \brief Determines whether the given declaration is an Objective-C
/// instance variable.
-bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
+bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
return isa<ObjCIvarDecl>(ND);
}
@@ -1206,7 +1260,8 @@ namespace {
if (Ctx)
Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
- ResultBuilder::Result Result(ND, 0, false, Accessible);
+ ResultBuilder::Result Result(ND, Results.getBasePriority(ND), 0, false,
+ Accessible);
Results.AddResult(Result, CurContext, Hiding, InBaseClass);
}
};
@@ -1256,7 +1311,7 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
- if (LangOpts.CPlusPlus0x) {
+ if (LangOpts.CPlusPlus11) {
Results.AddResult(Result("auto", CCP_Type));
Results.AddResult(Result("char16_t", CCP_Type));
Results.AddResult(Result("char32_t", CCP_Type));
@@ -1421,7 +1476,7 @@ static const char *GetCompletionTypeString(QualType T,
// Anonymous tag types are constant strings.
if (const TagType *TagT = dyn_cast<TagType>(T))
if (TagDecl *Tag = TagT->getDecl())
- if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
+ if (!Tag->hasNameForLinkage()) {
switch (Tag->getTagKind()) {
case TTK_Struct: return "struct <anonymous>";
case TTK_Interface: return "__interface <anonymous>";
@@ -1906,7 +1961,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
// FIXME: Rethrow?
- if (SemaRef.getLangOpts().CPlusPlus0x) {
+ if (SemaRef.getLangOpts().CPlusPlus11) {
// nullptr
Builder.AddResultTypeChunk("std::nullptr_t");
Builder.AddTypedTextChunk("nullptr");
@@ -1997,7 +2052,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
/// type chunk.
static void AddResultTypeChunk(ASTContext &Context,
const PrintingPolicy &Policy,
- NamedDecl *ND,
+ const NamedDecl *ND,
CodeCompletionBuilder &Result) {
if (!ND)
return;
@@ -2009,19 +2064,20 @@ static void AddResultTypeChunk(ASTContext &Context,
// Determine the type of the declaration (if it has a type).
QualType T;
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
T = Function->getResultType();
- else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
T = Method->getResultType();
- else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ else if (const FunctionTemplateDecl *FunTmpl =
+ dyn_cast<FunctionTemplateDecl>(ND))
T = FunTmpl->getTemplatedDecl()->getResultType();
- else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
else if (isa<UnresolvedUsingValueDecl>(ND)) {
/* Do nothing: ignore unresolved using declarations*/
- } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
+ } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
T = Value->getType();
- } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+ } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
T = Property->getType();
if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
@@ -2031,7 +2087,8 @@ static void AddResultTypeChunk(ASTContext &Context,
Result.getAllocator()));
}
-static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
+static void MaybeAddSentinel(ASTContext &Context,
+ const NamedDecl *FunctionOrMethod,
CodeCompletionBuilder &Result) {
if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
if (Sentinel->getSentinel() == 0) {
@@ -2064,7 +2121,7 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
static std::string FormatFunctionParameter(ASTContext &Context,
const PrintingPolicy &Policy,
- ParmVarDecl *Param,
+ const ParmVarDecl *Param,
bool SuppressName = false,
bool SuppressBlock = false) {
bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
@@ -2090,36 +2147,35 @@ static std::string FormatFunctionParameter(ASTContext &Context,
// The argument for a block pointer parameter is a block literal with
// the appropriate type.
- FunctionTypeLoc *Block = 0;
- FunctionProtoTypeLoc *BlockProto = 0;
+ FunctionTypeLoc Block;
+ FunctionProtoTypeLoc BlockProto;
TypeLoc TL;
if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
while (true) {
// Look through typedefs.
if (!SuppressBlock) {
- if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
- if (TypeSourceInfo *InnerTSInfo
- = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
+ if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
+ if (TypeSourceInfo *InnerTSInfo =
+ TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
continue;
}
}
// Look through qualified types
- if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
- TL = QualifiedTL->getUnqualifiedLoc();
+ if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
+ TL = QualifiedTL.getUnqualifiedLoc();
continue;
}
}
// Try to get the function prototype behind the block pointer type,
// then we're done.
- if (BlockPointerTypeLoc *BlockPtr
- = dyn_cast<BlockPointerTypeLoc>(&TL)) {
- TL = BlockPtr->getPointeeLoc().IgnoreParens();
- Block = dyn_cast<FunctionTypeLoc>(&TL);
- BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
+ TL = BlockPtr.getPointeeLoc().IgnoreParens();
+ Block = TL.getAs<FunctionTypeLoc>();
+ BlockProto = TL.getAs<FunctionProtoTypeLoc>();
}
break;
}
@@ -2147,27 +2203,27 @@ static std::string FormatFunctionParameter(ASTContext &Context,
// We have the function prototype behind the block pointer type, as it was
// written in the source.
std::string Result;
- QualType ResultType = Block->getTypePtr()->getResultType();
+ QualType ResultType = Block.getTypePtr()->getResultType();
if (!ResultType->isVoidType() || SuppressBlock)
ResultType.getAsStringInternal(Result, Policy);
// Format the parameter list.
std::string Params;
- if (!BlockProto || Block->getNumArgs() == 0) {
- if (BlockProto && BlockProto->getTypePtr()->isVariadic())
+ if (!BlockProto || Block.getNumArgs() == 0) {
+ if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Params = "(...)";
else
Params = "(void)";
} else {
Params += "(";
- for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
+ for (unsigned I = 0, N = Block.getNumArgs(); I != N; ++I) {
if (I)
Params += ", ";
- Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
+ Params += FormatFunctionParameter(Context, Policy, Block.getArg(I),
/*SuppressName=*/false,
/*SuppressBlock=*/true);
- if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
+ if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Params += ", ...";
}
Params += ")";
@@ -2195,14 +2251,14 @@ static std::string FormatFunctionParameter(ASTContext &Context,
/// \brief Add function parameter chunks to the given code completion string.
static void AddFunctionParameterChunks(ASTContext &Context,
const PrintingPolicy &Policy,
- FunctionDecl *Function,
+ const FunctionDecl *Function,
CodeCompletionBuilder &Result,
unsigned Start = 0,
bool InOptional = false) {
bool FirstParameter = true;
for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
- ParmVarDecl *Param = Function->getParamDecl(P);
+ const ParmVarDecl *Param = Function->getParamDecl(P);
if (Param->hasDefaultArg() && !InOptional) {
// When we see an optional default argument, put that argument and
@@ -2248,7 +2304,7 @@ static void AddFunctionParameterChunks(ASTContext &Context,
/// \brief Add template parameter chunks to the given code completion string.
static void AddTemplateParameterChunks(ASTContext &Context,
const PrintingPolicy &Policy,
- TemplateDecl *Template,
+ const TemplateDecl *Template,
CodeCompletionBuilder &Result,
unsigned MaxParameters = 0,
unsigned Start = 0,
@@ -2346,7 +2402,7 @@ AddQualifierToCompletionString(CodeCompletionBuilder &Result,
static void
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
- FunctionDecl *Function) {
+ const FunctionDecl *Function) {
const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>();
if (!Proto || !Proto->getTypeQuals())
@@ -2383,7 +2439,8 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
/// \brief Add the name of the given declaration
static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
- NamedDecl *ND, CodeCompletionBuilder &Result) {
+ const NamedDecl *ND,
+ CodeCompletionBuilder &Result) {
DeclarationName Name = ND->getDeclName();
if (!Name)
return;
@@ -2484,6 +2541,27 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
if (Declaration) {
Result.addParentContext(Declaration->getDeclContext());
Pattern->ParentName = Result.getParentName();
+ // Provide code completion comment for self.GetterName where
+ // GetterName is the getter method for a property with name
+ // different from the property name (declared via a property
+ // getter attribute.
+ const NamedDecl *ND = Declaration;
+ if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND))
+ if (M->isPropertyAccessor())
+ if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl())
+ if (PDecl->getGetterName() == M->getSelector() &&
+ PDecl->getIdentifier() != M->getIdentifier()) {
+ if (const RawComment *RC =
+ Ctx.getRawCommentForAnyRedecl(M)) {
+ Result.addBriefComment(RC->getBriefText(Ctx));
+ Pattern->BriefComment = Result.getBriefComment();
+ }
+ else if (const RawComment *RC =
+ Ctx.getRawCommentForAnyRedecl(PDecl)) {
+ Result.addBriefComment(RC->getBriefText(Ctx));
+ Pattern->BriefComment = Result.getBriefComment();
+ }
+ }
}
return Pattern;
@@ -2495,8 +2573,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
}
if (Kind == RK_Macro) {
- MacroInfo *MI = PP.getMacroInfoHistory(Macro);
- assert(MI && "Not a macro?");
+ const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro);
+ assert(MD && "Not a macro?");
+ const MacroInfo *MI = MD->getMacroInfo();
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Macro->getName()));
@@ -2540,14 +2619,19 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
}
assert(Kind == RK_Declaration && "Missed a result kind?");
- NamedDecl *ND = Declaration;
+ const NamedDecl *ND = Declaration;
Result.addParentContext(ND->getDeclContext());
if (IncludeBriefComments) {
// Add documentation comment, if it exists.
if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Result.addBriefComment(RC->getBriefText(Ctx));
- }
+ }
+ else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
+ if (OMD->isPropertyAccessor())
+ if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
+ if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
+ Result.addBriefComment(RC->getBriefText(Ctx));
}
if (StartsNestedNameSpecifier) {
@@ -2565,7 +2649,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
AddResultTypeChunk(Ctx, Policy, ND, Result);
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
AddTypedNameChunk(Ctx, Policy, ND, Result);
@@ -2576,7 +2660,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
+ if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
@@ -2630,7 +2714,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
- if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
+ if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
Result.AddTypedTextChunk(
@@ -2641,7 +2725,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
- if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+ if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Selector Sel = Method->getSelector();
if (Sel.isUnarySelector()) {
Result.AddTypedTextChunk(Result.getAllocator().CopyString(
@@ -2662,8 +2746,8 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Result.AddTypedTextChunk("");
}
unsigned Idx = 0;
- for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
+ for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
P != PEnd; (void)++P, ++Idx) {
if (Idx > 0) {
std::string Keyword;
@@ -2827,7 +2911,7 @@ unsigned clang::getMacroUsagePriority(StringRef MacroName,
return Priority;
}
-CXCursorKind clang::getCursorKindForDecl(Decl *D) {
+CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
if (!D)
return CXCursor_UnexposedDecl;
@@ -2887,7 +2971,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) {
return CXCursor_ModuleImportDecl;
default:
- if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
switch (TD->getTagKind()) {
case TTK_Interface: // fall through
case TTK_Struct: return CXCursor_StructDecl;
@@ -2930,7 +3014,7 @@ static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
Results.AddResult(Result("__FUNCTION__", CCP_Constant));
- if (LangOpts.C99 || LangOpts.CPlusPlus0x)
+ if (LangOpts.C99 || LangOpts.CPlusPlus11)
Results.AddResult(Result("__func__", CCP_Constant));
Results.ExitScope();
}
@@ -3036,7 +3120,7 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
M != MEnd; ++M) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
- CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
+ const CXXMethodDecl *Overridden = *M;
if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
continue;
@@ -3092,7 +3176,7 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
typedef CodeCompletionResult Result;
if (Path.empty()) {
// Enumerate all top-level modules.
- llvm::SmallVector<Module *, 8> Modules;
+ SmallVector<Module *, 8> Modules;
PP.getHeaderSearchInfo().collectAllModules(Modules);
for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
Builder.AddTypedTextChunk(
@@ -3265,7 +3349,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
// the initial opening bracket '[' missing. Add appropriate completions.
if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
DS.getTypeSpecType() == DeclSpec::TST_typename &&
- DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
+ DS.getStorageClassSpec() == DeclSpec::SCS_unspecified &&
!DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
@@ -3395,7 +3479,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
P != PEnd;
++P) {
if (AddedProperties.insert(P->getIdentifier()))
- Results.MaybeAddResult(Result(*P, 0), CurContext);
+ Results.MaybeAddResult(Result(*P, Results.getBasePriority(*P), 0),
+ CurContext);
}
// Add nullary methods
@@ -3432,9 +3517,11 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
} else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
if (AllowCategories) {
// Look through categories.
- for (ObjCCategoryDecl *Category = IFace->getCategoryList();
- Category; Category = Category->getNextClassCategory())
- AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
+ for (ObjCInterfaceDecl::known_categories_iterator
+ Cat = IFace->known_categories_begin(),
+ CatEnd = IFace->known_categories_end();
+ Cat != CatEnd; ++Cat)
+ AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results);
}
@@ -3642,6 +3729,9 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
if (getLangOpts().C99 &&
!(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
Results.AddResult("restrict");
+ if (getLangOpts().C11 &&
+ !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
+ Results.AddResult("_Atomic");
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
@@ -3724,8 +3814,7 @@ void Sema::CodeCompleteCase(Scope *S) {
if (EnumeratorsSeen.count(*E))
continue;
- CodeCompletionResult R(*E, Qualifier);
- R.Priority = CCP_EnumInCase;
+ CodeCompletionResult R(*E, CCP_EnumInCase, Qualifier);
Results.AddResult(R, CurContext, 0, false);
}
Results.ExitScope();
@@ -4094,7 +4183,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
NS = OrigToLatest.begin(),
NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
- Results.AddResult(CodeCompletionResult(NS->second, 0),
+ Results.AddResult(CodeCompletionResult(
+ NS->second, Results.getBasePriority(NS->second), 0),
CurContext, 0, false);
Results.ExitScope();
}
@@ -4308,7 +4398,8 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
continue;
if (Known.insert(Var->getIdentifier()))
- Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
+ Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
+ CurContext, 0, false);
}
}
@@ -4410,6 +4501,14 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("class");
Results.AddResult(Result(Builder.TakeString()));
+
+ if (Results.getSema().getLangOpts().Modules) {
+ // @import name
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("module");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
}
void Sema::CodeCompleteObjCAtDirective(Scope *S) {
@@ -4757,10 +4856,15 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
bool InOriginalClass = true) {
typedef CodeCompletionResult Result;
Container = getContainerDef(Container);
+ ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
+ bool isRootClass = IFace && !IFace->getSuperClass();
for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
MEnd = Container->meth_end();
M != MEnd; ++M) {
- if (M->isInstanceMethod() == WantInstanceMethods) {
+ // The instance methods on the root class can be messaged via the
+ // metaclass.
+ if (M->isInstanceMethod() == WantInstanceMethods ||
+ (isRootClass && !WantInstanceMethods)) {
// Check whether the selector identifiers we've been given are a
// subset of the identifiers for this particular method.
if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
@@ -4770,7 +4874,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
if (!Selectors.insert(M->getSelector()))
continue;
- Result R = Result(*M, 0);
+ Result R = Result(*M, Results.getBasePriority(*M), 0);
R.StartParameter = NumSelIdents;
R.AllParametersAreInformative = (WantKind != MK_Any);
if (!InOriginalClass)
@@ -4793,7 +4897,6 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
}
}
- ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
if (!IFace || !IFace->hasDefinition())
return;
@@ -4805,9 +4908,13 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
CurContext, Selectors, AllowSameLength, Results, false);
// Add methods in categories.
- for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
- CatDecl = CatDecl->getNextClassCategory()) {
- AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
+ for (ObjCInterfaceDecl::known_categories_iterator
+ Cat = IFace->known_categories_begin(),
+ CatEnd = IFace->known_categories_end();
+ Cat != CatEnd; ++Cat) {
+ ObjCCategoryDecl *CatDecl = *Cat;
+
+ AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
NumSelIdents, CurContext, Selectors, AllowSameLength,
Results, InOriginalClass);
@@ -4946,6 +5053,11 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
Builder.AddTextChunk("sender");
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
+
+ // If we're completing the return type, provide 'instancetype'.
+ if (!IsParameter) {
+ Results.AddResult(CodeCompletionResult("instancetype"));
+ }
// Add various builtin type names and specifiers.
AddOrdinaryNameResults(PCC_Type, S, *this, Results);
@@ -5075,11 +5187,14 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
// Check in categories or class extensions.
if (!SuperMethod) {
- for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
- Category = Category->getNextClassCategory())
- if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
+ for (ObjCInterfaceDecl::known_categories_iterator
+ Cat = Class->known_categories_begin(),
+ CatEnd = Class->known_categories_end();
+ Cat != CatEnd; ++Cat) {
+ if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
CurMethod->isInstanceMethod())))
break;
+ }
}
}
@@ -5163,7 +5278,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCMessageReceiver,
- getLangOpts().CPlusPlus0x
+ getLangOpts().CPlusPlus11
? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
: &ResultBuilder::IsObjCMessageReceiver);
@@ -5182,7 +5297,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
}
- if (getLangOpts().CPlusPlus0x)
+ if (getLangOpts().CPlusPlus11)
addThisCompletion(*this, Results);
Results.ExitScope();
@@ -5224,7 +5339,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
} else {
// "super" may be the name of a type or variable. Figure out which
// it is.
- IdentifierInfo *Super = &Context.Idents.get("super");
+ IdentifierInfo *Super = getSuperIdentifier();
NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
LookupOrdinaryName);
if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
@@ -5274,7 +5389,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
if (R.Kind == Result::RK_Declaration &&
isa<ObjCMethodDecl>(R.Declaration)) {
if (R.Priority <= BestPriority) {
- ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
+ const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
if (NumSelIdents <= Method->param_size()) {
QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
->getType();
@@ -5362,7 +5477,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
NumSelIdents))
continue;
- Result R(MethList->Method, 0);
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
R.StartParameter = NumSelIdents;
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, SemaRef.CurContext);
@@ -5538,7 +5653,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
if (!Selectors.insert(MethList->Method->getSelector()))
continue;
- Result R(MethList->Method, 0);
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
R.StartParameter = NumSelIdents;
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, CurContext);
@@ -5656,7 +5771,8 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
// Record any protocols we find.
if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
if (!OnlyForwardDeclarations || !Proto->hasDefinition())
- Results.AddResult(Result(Proto, 0), CurContext, 0, false);
+ Results.AddResult(Result(Proto, Results.getBasePriority(Proto), 0),
+ CurContext, 0, false);
}
}
@@ -5724,7 +5840,8 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
(!OnlyUnimplemented || !Class->getImplementation()))
- Results.AddResult(Result(Class, 0), CurContext, 0, false);
+ Results.AddResult(Result(Class, Results.getBasePriority(Class), 0),
+ CurContext, 0, false);
}
}
@@ -5806,11 +5923,15 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
NamedDecl *CurClass
= LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
- if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
- for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
- Category = Category->getNextClassCategory())
- CategoryNames.insert(Category->getIdentifier());
-
+ if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
+ for (ObjCInterfaceDecl::visible_categories_iterator
+ Cat = Class->visible_categories_begin(),
+ CatEnd = Class->visible_categories_end();
+ Cat != CatEnd; ++Cat) {
+ CategoryNames.insert(Cat->getIdentifier());
+ }
+ }
+
// Add all of the categories we know about.
Results.EnterNewScope();
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
@@ -5819,7 +5940,8 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
D != DEnd; ++D)
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
if (CategoryNames.insert(Category->getIdentifier()))
- Results.AddResult(Result(Category, 0), CurContext, 0, false);
+ Results.AddResult(Result(Category, Results.getBasePriority(Category),0),
+ CurContext, 0, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
@@ -5852,11 +5974,15 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Results.EnterNewScope();
bool IgnoreImplemented = true;
while (Class) {
- for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
- Category = Category->getNextClassCategory())
- if ((!IgnoreImplemented || !Category->getImplementation()) &&
- CategoryNames.insert(Category->getIdentifier()))
- Results.AddResult(Result(Category, 0), CurContext, 0, false);
+ for (ObjCInterfaceDecl::visible_categories_iterator
+ Cat = Class->visible_categories_begin(),
+ CatEnd = Class->visible_categories_end();
+ Cat != CatEnd; ++Cat) {
+ if ((!IgnoreImplemented || !Cat->getImplementation()) &&
+ CategoryNames.insert(Cat->getIdentifier()))
+ Results.AddResult(Result(*Cat, Results.getBasePriority(*Cat), 0),
+ CurContext, 0, false);
+ }
Class = Class->getSuperClass();
IgnoreImplemented = false;
@@ -5956,7 +6082,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
for(; Class; Class = Class->getSuperClass()) {
for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Ivar = Ivar->getNextIvar()) {
- Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
+ Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), 0),
+ CurContext, 0, false);
// Determine whether we've seen an ivar with a name similar to the
// property.
@@ -6032,12 +6159,14 @@ static void FindImplementableMethods(ASTContext &Context,
KnownMethods, InOriginalClass);
// Add methods from any class extensions and categories.
- for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
- Cat = Cat->getNextClassCategory())
- FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
- WantInstanceMethods, ReturnType,
+ for (ObjCInterfaceDecl::visible_categories_iterator
+ Cat = IFace->visible_categories_begin(),
+ CatEnd = IFace->visible_categories_end();
+ Cat != CatEnd; ++Cat) {
+ FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
KnownMethods, false);
-
+ }
+
// Visit the superclass.
if (IFace->getSuperClass())
FindImplementableMethods(Context, IFace->getSuperClass(),
@@ -6167,7 +6296,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// The uppercased name of the property name.
std::string UpperKey = PropName->getName();
if (!UpperKey.empty())
- UpperKey[0] = toupper(UpperKey[0]);
+ UpperKey[0] = toUppercase(UpperKey[0]);
bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
@@ -6897,9 +7026,12 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
IFace = Category->getClassInterface();
if (IFace) {
- for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
- Category = Category->getNextClassCategory())
- Containers.push_back(Category);
+ for (ObjCInterfaceDecl::visible_categories_iterator
+ Cat = IFace->visible_categories_begin(),
+ CatEnd = IFace->visible_categories_end();
+ Cat != CatEnd; ++Cat) {
+ Containers.push_back(*Cat);
+ }
}
for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
@@ -6975,7 +7107,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
continue;
}
- Result R(MethList->Method, 0);
+ Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0);
R.StartParameter = NumSelIdents;
R.AllParametersAreInformative = false;
R.DeclaringEntity = true;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 0092d5dab1f4..adf3505633bd 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -12,15 +12,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/CXXFieldCollector.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -28,18 +24,21 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Basic/PartialDiagnostic.h"
-#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
-// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/HeaderSearch.h" // FIXME: Sema shouldn't depend on Lex
+#include "clang/Lex/ModuleLoader.h" // FIXME: Sema shouldn't depend on Lex
+#include "clang/Lex/Preprocessor.h" // FIXME: Sema shouldn't depend on Lex
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Triple.h"
#include <algorithm>
@@ -677,9 +676,9 @@ Corrected:
(isa<TypeDecl>(UnderlyingFirstDecl) ||
isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) ||
isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) {
- UnqualifiedDiag = diag::err_unknown_typename_suggest;
- QualifiedDiag = diag::err_unknown_nested_typename_suggest;
- }
+ UnqualifiedDiag = diag::err_unknown_typename_suggest;
+ QualifiedDiag = diag::err_unknown_nested_typename_suggest;
+ }
if (SS.isEmpty())
Diag(NameLoc, UnqualifiedDiag)
@@ -1097,7 +1096,7 @@ void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S,
bool ExplicitInstantiationOrSpecialization) {
- return IdResolver.isDeclInScope(D, Ctx, Context, S,
+ return IdResolver.isDeclInScope(D, Ctx, S,
ExplicitInstantiationOrSpecialization);
}
@@ -1175,6 +1174,31 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
return false;
}
+// We need this to handle
+//
+// typedef struct {
+// void *foo() { return 0; }
+// } A;
+//
+// When we see foo we don't know if after the typedef we will get 'A' or '*A'
+// for example. If 'A', foo will have external linkage. If we have '*A',
+// foo will have no linkage. Since we can't know untill we get to the end
+// of the typedef, this function finds out if D might have non external linkage.
+// Callers should verify at the end of the TU if it D has external linkage or
+// not.
+bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) {
+ const DeclContext *DC = D->getDeclContext();
+ while (!DC->isTranslationUnit()) {
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(DC)){
+ if (!RD->hasNameForLinkage())
+ return true;
+ }
+ DC = DC->getParent();
+ }
+
+ return !D->hasExternalLinkage();
+}
+
bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
assert(D);
@@ -1224,10 +1248,7 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
}
// Only warn for unused decls internal to the translation unit.
- if (D->getLinkage() == ExternalLinkage)
- return false;
-
- return true;
+ return mightHaveNonExternalLinkage(D);
}
void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
@@ -1368,7 +1389,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (!D->getDeclName()) continue;
// Diagnose unused variables in this scope.
- if (!S->hasErrorOccurred())
+ if (!S->hasUnrecoverableErrorOccurred())
DiagnoseUnusedDecl(D);
// If this was a forward reference to a label, verify it was defined.
@@ -1465,6 +1486,24 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
return S;
}
+/// \brief Looks up the declaration of "struct objc_super" and
+/// saves it for later use in building builtin declaration of
+/// objc_msgSendSuper and objc_msgSendSuper_stret. If no such
+/// pre-existing declaration exists no action takes place.
+static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S,
+ IdentifierInfo *II) {
+ if (!II->isStr("objc_msgSendSuper"))
+ return;
+ ASTContext &Context = ThisSema.Context;
+
+ LookupResult Result(ThisSema, &Context.Idents.get("objc_super"),
+ SourceLocation(), Sema::LookupTagName);
+ ThisSema.LookupName(Result, S);
+ if (Result.getResultKind() == LookupResult::Found)
+ if (const TagDecl *TD = Result.getAsSingle<TagDecl>())
+ Context.setObjCSuperType(Context.getTagDeclType(TD));
+}
+
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at
/// file scope. lazily create a decl for it. ForRedeclaration is true
/// if we're creating this built-in in anticipation of redeclaring the
@@ -1472,6 +1511,8 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
Scope *S, bool ForRedeclaration,
SourceLocation Loc) {
+ LookupPredefedObjCSuperType(*this, S, II);
+
Builtin::ID BID = (Builtin::ID)bid;
ASTContext::GetBuiltinTypeError Error;
@@ -1516,7 +1557,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
Context.getTranslationUnitDecl(),
Loc, Loc, II, R, /*TInfo=*/0,
SC_Extern,
- SC_None, false,
+ false,
/*hasPrototype=*/true);
New->setImplicit();
@@ -1529,7 +1570,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
ParmVarDecl::Create(Context, New, SourceLocation(),
SourceLocation(), 0,
FT->getArgType(i), /*TInfo=*/0,
- SC_None, SC_None, 0);
+ SC_None, 0);
parm->setScopeInfo(0, i);
Params.push_back(parm);
}
@@ -1549,6 +1590,49 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
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(ASTContext &context,
+ NamedDecl *decl,
+ LookupResult &previous){
+ // This is only interesting when modules are enabled.
+ if (!context.getLangOpts().Modules)
+ 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 (!old->isHidden())
+ continue;
+
+ // If either has no-external linkage, ignore the old declaration.
+ // If this declaration would have external linkage if it were the first
+ // declaration of this name, then it may in fact be a redeclaration of
+ // some hidden declaration, so include those too. We don't need to worry
+ // about some previous visible declaration giving this declaration external
+ // linkage, because in that case, we'll mark this declaration as a redecl
+ // of the visible decl, and that decl will already be a redecl of the
+ // hidden declaration if that's appropriate.
+ //
+ // Don't cache this linkage computation, because it's not yet correct: we
+ // may later give this declaration a previous declaration which changes
+ // its linkage.
+ if (old->getLinkage() != ExternalLinkage ||
+ !decl->hasExternalLinkageUncached())
+ filter.erase();
+ }
+
+ filter.done();
+}
+
bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
QualType OldType;
if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
@@ -1769,26 +1853,164 @@ DeclHasAttr(const Decl *D, const Attr *A) {
return false;
}
-bool Sema::mergeDeclAttribute(Decl *D, InheritableAttr *Attr) {
+static bool isAttributeTargetADefinition(Decl *D) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ return VD->isThisDeclarationADefinition();
+ if (TagDecl *TD = dyn_cast<TagDecl>(D))
+ return TD->isCompleteDefinition() || TD->isBeingDefined();
+ return true;
+}
+
+/// Merge alignment attributes from \p Old to \p New, taking into account the
+/// special semantics of C11's _Alignas specifier and C++11's alignas attribute.
+///
+/// \return \c true if any attributes were added to \p New.
+static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
+ // Look for alignas attributes on Old, and pick out whichever attribute
+ // specifies the strictest alignment requirement.
+ AlignedAttr *OldAlignasAttr = 0;
+ AlignedAttr *OldStrictestAlignAttr = 0;
+ unsigned OldAlign = 0;
+ for (specific_attr_iterator<AlignedAttr>
+ I = Old->specific_attr_begin<AlignedAttr>(),
+ E = Old->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ // FIXME: We have no way of representing inherited dependent alignments
+ // in a case like:
+ // template<int A, int B> struct alignas(A) X;
+ // template<int A, int B> struct alignas(B) X {};
+ // For now, we just ignore any alignas attributes which are not on the
+ // definition in such a case.
+ if (I->isAlignmentDependent())
+ return false;
+
+ if (I->isAlignas())
+ OldAlignasAttr = *I;
+
+ unsigned Align = I->getAlignment(S.Context);
+ if (Align > OldAlign) {
+ OldAlign = Align;
+ OldStrictestAlignAttr = *I;
+ }
+ }
+
+ // Look for alignas attributes on New.
+ AlignedAttr *NewAlignasAttr = 0;
+ unsigned NewAlign = 0;
+ for (specific_attr_iterator<AlignedAttr>
+ I = New->specific_attr_begin<AlignedAttr>(),
+ E = New->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ if (I->isAlignmentDependent())
+ return false;
+
+ if (I->isAlignas())
+ NewAlignasAttr = *I;
+
+ unsigned Align = I->getAlignment(S.Context);
+ if (Align > NewAlign)
+ NewAlign = Align;
+ }
+
+ if (OldAlignasAttr && NewAlignasAttr && OldAlign != NewAlign) {
+ // Both declarations have 'alignas' attributes. We require them to match.
+ // C++11 [dcl.align]p6 and C11 6.7.5/7 both come close to saying this, but
+ // fall short. (If two declarations both have alignas, they must both match
+ // every definition, and so must match each other if there is a definition.)
+
+ // If either declaration only contains 'alignas(0)' specifiers, then it
+ // specifies the natural alignment for the type.
+ if (OldAlign == 0 || NewAlign == 0) {
+ QualType Ty;
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(New))
+ Ty = VD->getType();
+ else
+ Ty = S.Context.getTagDeclType(cast<TagDecl>(New));
+
+ if (OldAlign == 0)
+ OldAlign = S.Context.getTypeAlign(Ty);
+ if (NewAlign == 0)
+ NewAlign = S.Context.getTypeAlign(Ty);
+ }
+
+ if (OldAlign != NewAlign) {
+ S.Diag(NewAlignasAttr->getLocation(), diag::err_alignas_mismatch)
+ << (unsigned)S.Context.toCharUnitsFromBits(OldAlign).getQuantity()
+ << (unsigned)S.Context.toCharUnitsFromBits(NewAlign).getQuantity();
+ S.Diag(OldAlignasAttr->getLocation(), diag::note_previous_declaration);
+ }
+ }
+
+ if (OldAlignasAttr && !NewAlignasAttr && isAttributeTargetADefinition(New)) {
+ // C++11 [dcl.align]p6:
+ // if any declaration of an entity has an alignment-specifier,
+ // every defining declaration of that entity shall specify an
+ // equivalent alignment.
+ // C11 6.7.5/7:
+ // If the definition of an object does not have an alignment
+ // specifier, any other declaration of that object shall also
+ // have no alignment specifier.
+ S.Diag(New->getLocation(), diag::err_alignas_missing_on_definition)
+ << OldAlignasAttr->isC11();
+ S.Diag(OldAlignasAttr->getLocation(), diag::note_alignas_on_declaration)
+ << OldAlignasAttr->isC11();
+ }
+
+ bool AnyAdded = false;
+
+ // Ensure we have an attribute representing the strictest alignment.
+ if (OldAlign > NewAlign) {
+ AlignedAttr *Clone = OldStrictestAlignAttr->clone(S.Context);
+ Clone->setInherited(true);
+ New->addAttr(Clone);
+ AnyAdded = true;
+ }
+
+ // Ensure we have an alignas attribute if the old declaration had one.
+ if (OldAlignasAttr && !NewAlignasAttr &&
+ !(AnyAdded && OldStrictestAlignAttr->isAlignas())) {
+ AlignedAttr *Clone = OldAlignasAttr->clone(S.Context);
+ Clone->setInherited(true);
+ New->addAttr(Clone);
+ AnyAdded = true;
+ }
+
+ return AnyAdded;
+}
+
+static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr,
+ bool Override) {
InheritableAttr *NewAttr = NULL;
+ unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr))
- NewAttr = mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
- AA->getIntroduced(), AA->getDeprecated(),
- AA->getObsoleted(), AA->getUnavailable(),
- AA->getMessage());
+ NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
+ AA->getIntroduced(), AA->getDeprecated(),
+ AA->getObsoleted(), AA->getUnavailable(),
+ AA->getMessage(), Override,
+ AttrSpellingListIndex);
else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr))
- NewAttr = mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility());
+ NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
+ AttrSpellingListIndex);
+ else if (TypeVisibilityAttr *VA = dyn_cast<TypeVisibilityAttr>(Attr))
+ NewAttr = S.mergeTypeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
+ AttrSpellingListIndex);
else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr))
- NewAttr = mergeDLLImportAttr(D, ImportA->getRange());
+ NewAttr = S.mergeDLLImportAttr(D, ImportA->getRange(),
+ AttrSpellingListIndex);
else if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr))
- NewAttr = mergeDLLExportAttr(D, ExportA->getRange());
+ NewAttr = S.mergeDLLExportAttr(D, ExportA->getRange(),
+ AttrSpellingListIndex);
else if (FormatAttr *FA = dyn_cast<FormatAttr>(Attr))
- NewAttr = mergeFormatAttr(D, FA->getRange(), FA->getType(),
- FA->getFormatIdx(), FA->getFirstArg());
+ NewAttr = S.mergeFormatAttr(D, FA->getRange(), FA->getType(),
+ FA->getFormatIdx(), FA->getFirstArg(),
+ AttrSpellingListIndex);
else if (SectionAttr *SA = dyn_cast<SectionAttr>(Attr))
- NewAttr = mergeSectionAttr(D, SA->getRange(), SA->getName());
+ NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
+ 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 = 0;
else if (!DeclHasAttr(D, Attr))
- NewAttr = cast<InheritableAttr>(Attr->clone(Context));
+ NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
if (NewAttr) {
NewAttr->setInherited(true);
@@ -1839,6 +2061,31 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
++I;
continue; // regular attr merging will take care of validating this.
}
+
+ if (isa<C11NoReturnAttr>(NewAttribute)) {
+ // C's _Noreturn is allowed to be added to a function after it is defined.
+ ++I;
+ continue;
+ } else if (const AlignedAttr *AA = dyn_cast<AlignedAttr>(NewAttribute)) {
+ if (AA->isAlignas()) {
+ // C++11 [dcl.align]p6:
+ // if any declaration of an entity has an alignment-specifier,
+ // every defining declaration of that entity shall specify an
+ // equivalent alignment.
+ // C11 6.7.5/7:
+ // If the definition of an object does not have an alignment
+ // specifier, any other declaration of that object shall also
+ // have no alignment specifier.
+ S.Diag(Def->getLocation(), diag::err_alignas_missing_on_definition)
+ << AA->isC11();
+ S.Diag(NewAttribute->getLocation(), diag::note_alignas_on_declaration)
+ << AA->isC11();
+ NewAttributes.erase(NewAttributes.begin() + I);
+ --E;
+ continue;
+ }
+ }
+
S.Diag(NewAttribute->getLocation(),
diag::warn_attribute_precede_definition);
S.Diag(Def->getLocation(), diag::note_previous_definition);
@@ -1848,8 +2095,11 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
}
/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
-void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
- bool MergeDeprecation) {
+void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
+ AvailabilityMergeKind AMK) {
+ if (!Old->hasAttrs() && !New->hasAttrs())
+ return;
+
// attributes declared post-definition are currently ignored
checkNewAttributesAfterDef(*this, New, Old);
@@ -1866,17 +2116,31 @@ void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
i = Old->specific_attr_begin<InheritableAttr>(),
e = Old->specific_attr_end<InheritableAttr>();
i != e; ++i) {
+ bool Override = false;
// Ignore deprecated/unavailable/availability attributes if requested.
- if (!MergeDeprecation &&
- (isa<DeprecatedAttr>(*i) ||
- isa<UnavailableAttr>(*i) ||
- isa<AvailabilityAttr>(*i)))
- continue;
+ if (isa<DeprecatedAttr>(*i) ||
+ isa<UnavailableAttr>(*i) ||
+ isa<AvailabilityAttr>(*i)) {
+ switch (AMK) {
+ case AMK_None:
+ continue;
- if (mergeDeclAttribute(New, *i))
+ case AMK_Redeclaration:
+ break;
+
+ case AMK_Override:
+ Override = true;
+ break;
+ }
+ }
+
+ if (mergeDeclAttribute(*this, New, *i, Override))
foundAny = true;
}
+ if (mergeAlignedAttrs(*this, New, Old))
+ foundAny = true;
+
if (!foundAny) New->dropAttrs();
}
@@ -1884,7 +2148,25 @@ void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
/// to the new one.
static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
const ParmVarDecl *oldDecl,
- ASTContext &C) {
+ Sema &S) {
+ // C++11 [dcl.attr.depend]p2:
+ // The first declaration of a function shall specify the
+ // carries_dependency attribute for its declarator-id if any declaration
+ // of the function specifies the carries_dependency attribute.
+ if (newDecl->hasAttr<CarriesDependencyAttr>() &&
+ !oldDecl->hasAttr<CarriesDependencyAttr>()) {
+ S.Diag(newDecl->getAttr<CarriesDependencyAttr>()->getLocation(),
+ diag::err_carries_dependency_missing_on_first_decl) << 1/*Param*/;
+ // Find the first declaration of the parameter.
+ // FIXME: Should we build redeclaration chains for function parameters?
+ const FunctionDecl *FirstFD =
+ cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDeclaration();
+ const ParmVarDecl *FirstVD =
+ FirstFD->getParamDecl(oldDecl->getFunctionScopeIndex());
+ S.Diag(FirstVD->getLocation(),
+ diag::note_carries_dependency_missing_first_decl) << 1/*Param*/;
+ }
+
if (!oldDecl->hasAttrs())
return;
@@ -1898,7 +2180,8 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
if (!DeclHasAttr(newDecl, *i)) {
- InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C));
+ InheritableAttr *newAttr =
+ cast<InheritableParamAttr>((*i)->clone(S.Context));
newAttr->setInherited(true);
newDecl->addAttr(newAttr);
foundAny = true;
@@ -1966,6 +2249,22 @@ static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) {
return ABIDefaultCC == CC;
}
+template <typename T>
+static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
+ const DeclContext *DC = Old->getDeclContext();
+ if (DC->isRecord())
+ return false;
+
+ LanguageLinkage OldLinkage = Old->getLanguageLinkage();
+ if (OldLinkage == CXXLanguageLinkage &&
+ New->getDeclContext()->isExternCContext())
+ return true;
+ if (OldLinkage == CLanguageLinkage &&
+ New->getDeclContext()->isExternCXXContext())
+ return true;
+ return false;
+}
+
/// 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,
@@ -1987,6 +2286,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
Old = dyn_cast<FunctionDecl>(OldD);
if (!Old) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
+ if (New->getFriendObjectKind()) {
+ Diag(New->getLocation(), diag::err_using_decl_friend);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(),
+ diag::note_using_decl) << 0;
+ return true;
+ }
+
Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
Diag(Shadow->getTargetDecl()->getLocation(),
diag::note_using_decl_target);
@@ -2016,9 +2324,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
// Don't complain about this if we're in GNU89 mode and the old function
// is an extern inline function.
+ // Don't complain about specializations. They are not supposed to have
+ // storage classes.
if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
New->getStorageClass() == SC_Static &&
- Old->getStorageClass() != SC_Static &&
+ isExternalLinkage(Old->getLinkage()) &&
+ !New->getTemplateSpecializationInfo() &&
!canRedefineFunction(Old, getLangOpts())) {
if (getLangOpts().MicrosoftExt) {
Diag(New->getLocation(), diag::warn_static_non_static) << New;
@@ -2060,9 +2371,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
RequiresAdjustment = true;
// Don't complain about mismatches when the default CC is
- // effectively the same as the explict one.
+ // effectively the same as the explict one. Only Old decl contains correct
+ // information about storage class of CXXMethod.
} else if (OldTypeInfo.getCC() == CC_Default &&
- isABIDefaultCC(*this, NewTypeInfo.getCC(), New)) {
+ isABIDefaultCC(*this, NewTypeInfo.getCC(), Old)) {
NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
RequiresAdjustment = true;
@@ -2116,6 +2428,23 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
New->setType(QualType(NewType, 0));
NewQType = Context.getCanonicalType(New->getType());
}
+
+ // If this redeclaration makes the function inline, we may need to add it to
+ // UndefinedButUsed.
+ if (!Old->isInlined() && New->isInlined() &&
+ !New->hasAttr<GNUInlineAttr>() &&
+ (getLangOpts().CPlusPlus || !getLangOpts().GNUInline) &&
+ Old->isUsed(false) &&
+ !Old->isDefined() && !New->isThisDeclarationADefinition())
+ UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(),
+ SourceLocation()));
+
+ // If this redeclaration makes it newly gnu_inline, we don't want to warn
+ // about it.
+ if (New->hasAttr<GNUInlineAttr>() &&
+ Old->isInlined() && !Old->hasAttr<GNUInlineAttr>()) {
+ UndefinedButUsed.erase(Old->getCanonicalDecl());
+ }
if (getLangOpts().CPlusPlus) {
// (C++98 13.1p2):
@@ -2211,6 +2540,30 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
}
}
+ // C++11 [dcl.attr.noreturn]p1:
+ // The first declaration of a function shall specify the noreturn
+ // attribute if any declaration of that function specifies the noreturn
+ // attribute.
+ if (New->hasAttr<CXX11NoReturnAttr>() &&
+ !Old->hasAttr<CXX11NoReturnAttr>()) {
+ Diag(New->getAttr<CXX11NoReturnAttr>()->getLocation(),
+ diag::err_noreturn_missing_on_first_decl);
+ Diag(Old->getFirstDeclaration()->getLocation(),
+ diag::note_noreturn_missing_first_decl);
+ }
+
+ // C++11 [dcl.attr.depend]p2:
+ // The first declaration of a function shall specify the
+ // carries_dependency attribute for its declarator-id if any declaration
+ // of the function specifies the carries_dependency attribute.
+ if (New->hasAttr<CarriesDependencyAttr>() &&
+ !Old->hasAttr<CarriesDependencyAttr>()) {
+ Diag(New->getAttr<CarriesDependencyAttr>()->getLocation(),
+ diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/;
+ Diag(Old->getFirstDeclaration()->getLocation(),
+ diag::note_carries_dependency_missing_first_decl) << 0/*Function*/;
+ }
+
// (C++98 8.3.5p3):
// All declarations for a function shall agree exactly in both the
// return type and the parameter-type-list.
@@ -2226,6 +2579,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
assert(OldQTypeForComparison.isCanonical());
}
+ if (haveIncompatibleLanguageLinkages(Old, New)) {
+ Diag(New->getLocation(), diag::err_different_language_linkage) << New;
+ Diag(Old->getLocation(), PrevDiag);
+ return true;
+ }
+
if (OldQTypeForComparison == NewQType)
return MergeCompatibleFunctionDecls(New, Old, S);
@@ -2247,7 +2606,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
OldProto->arg_type_end());
NewQType = Context.getFunctionType(NewFuncType->getResultType(),
- ParamTypes.data(), ParamTypes.size(),
+ ParamTypes,
OldProto->getExtProtoInfo());
New->setType(NewQType);
New->setHasInheritedPrototype();
@@ -2262,7 +2621,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
SourceLocation(),
SourceLocation(), 0,
*ParamType, /*TInfo=*/0,
- SC_None, SC_None,
+ SC_None,
0);
Param->setScopeInfo(0, Params.size());
Param->setImplicit();
@@ -2330,8 +2689,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
diag::note_previous_declaration);
}
- New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],
- ArgTypes.size(),
+ New->setType(Context.getFunctionType(MergedReturn, ArgTypes,
OldProto->getExtProtoInfo()));
return MergeCompatibleFunctionDecls(New, Old, S);
}
@@ -2379,25 +2737,30 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
// Merge the attributes
mergeDeclAttributes(New, Old);
- // Merge the storage class.
- if (Old->getStorageClass() != SC_Extern &&
- Old->getStorageClass() != SC_None)
- New->setStorageClass(Old->getStorageClass());
-
// Merge "pure" flag.
if (Old->isPure())
New->setPure();
+ // Merge "used" flag.
+ if (Old->isUsed(false))
+ New->setUsed();
+
// Merge attributes from the parameters. These can mismatch with K&R
// declarations.
if (New->getNumParams() == Old->getNumParams())
for (unsigned i = 0, e = New->getNumParams(); i != e; ++i)
mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i),
- Context);
+ *this);
if (getLangOpts().CPlusPlus)
return MergeCXXFunctionDecl(New, Old, S);
+ // Merge the function types so the we get the composite types for the return
+ // and argument types.
+ QualType Merged = Context.mergeTypes(Old->getType(), New->getType());
+ if (!Merged.isNull())
+ New->setType(Merged);
+
return false;
}
@@ -2406,7 +2769,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
ObjCMethodDecl *oldMethod) {
// Merge the attributes, including deprecated/unavailable
- mergeDeclAttributes(newMethod, oldMethod, /* mergeDeprecation */true);
+ mergeDeclAttributes(newMethod, oldMethod, AMK_Override);
// Merge attributes from the parameters.
ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(),
@@ -2414,9 +2777,9 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
for (ObjCMethodDecl::param_iterator
ni = newMethod->param_begin(), ne = newMethod->param_end();
ni != ne && oi != oe; ++ni, ++oi)
- mergeParamDeclAttributes(*ni, *oi, Context);
+ mergeParamDeclAttributes(*ni, *oi, *this);
- CheckObjCMethodOverride(newMethod, oldMethod, true);
+ CheckObjCMethodOverride(newMethod, oldMethod);
}
/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and
@@ -2426,7 +2789,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
/// to here in AddInitializerToDecl. We can't check them before the initializer
/// is attached.
-void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
+void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) {
if (New->isInvalidDecl() || Old->isInvalidDecl())
return;
@@ -2447,19 +2810,17 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
// absence of a major array bound (8.3.4).
else if (Old->getType()->isIncompleteArrayType() &&
New->getType()->isArrayType()) {
- CanQual<ArrayType> OldArray
- = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
- CanQual<ArrayType> NewArray
- = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
- if (OldArray->getElementType() == NewArray->getElementType())
+ const ArrayType *OldArray = Context.getAsArrayType(Old->getType());
+ const ArrayType *NewArray = Context.getAsArrayType(New->getType());
+ if (Context.hasSameType(OldArray->getElementType(),
+ NewArray->getElementType()))
MergedT = New->getType();
} else if (Old->getType()->isArrayType() &&
New->getType()->isIncompleteArrayType()) {
- CanQual<ArrayType> OldArray
- = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
- CanQual<ArrayType> NewArray
- = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
- if (OldArray->getElementType() == NewArray->getElementType())
+ const ArrayType *OldArray = Context.getAsArrayType(Old->getType());
+ const ArrayType *NewArray = Context.getAsArrayType(New->getType());
+ if (Context.hasSameType(OldArray->getElementType(),
+ NewArray->getElementType()))
MergedT = Old->getType();
} else if (New->getType()->isObjCObjectPointerType()
&& Old->getType()->isObjCObjectPointerType()) {
@@ -2475,7 +2836,11 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
- New->setType(MergedT);
+
+ // Don't actually update the type on the new declaration if the old
+ // declaration was a extern declaration in a different scope.
+ if (!OldWasHidden)
+ New->setType(MergedT);
}
/// MergeVarDecl - We just parsed a variable 'New' which has the same name
@@ -2486,7 +2851,8 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
/// definitions here, since the initializer hasn't been attached.
///
-void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
+ bool PreviousWasHidden) {
// If the new decl is already invalid, don't do any other checking.
if (New->isInvalidDecl())
return;
@@ -2526,13 +2892,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
}
// Merge the types.
- MergeVarDeclTypes(New, Old);
+ MergeVarDeclTypes(New, Old, PreviousWasHidden);
if (New->isInvalidDecl())
return;
- // C99 6.2.2p4: Check if we have a static decl followed by a non-static.
+ // [dcl.stc]p8: Check if we have a non-static decl followed by a static.
if (New->getStorageClass() == SC_Static &&
- (Old->getStorageClass() == SC_None || Old->hasExternalStorage())) {
+ !New->isStaticDataMember() &&
+ isExternalLinkage(Old->getLinkage())) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -2548,8 +2915,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// identifier has external linkage.
if (New->hasExternalStorage() && Old->hasLinkage())
/* Okay */;
- else if (New->getStorageClass() != SC_Static &&
- Old->getStorageClass() == SC_Static) {
+ else if (New->getCanonicalDecl()->getStorageClass() != SC_Static &&
+ !New->isStaticDataMember() &&
+ Old->getCanonicalDecl()->getStorageClass() == SC_Static) {
Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -2562,8 +2930,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
- if (Old->hasExternalStorage() &&
- !New->hasLinkage() && New->isLocalVarDecl()) {
+ if (Old->hasLinkage() && New->isLocalVarDecl() &&
+ !New->hasExternalStorage()) {
Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -2601,17 +2969,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setInvalidDecl();
return;
}
- // c99 6.2.2 P4.
- // For an identifier declared with the storage-class specifier extern in a
- // scope in which a prior declaration of that identifier is visible, if
- // the prior declaration specifies internal or external linkage, the linkage
- // of the identifier at the later declaration is the same as the linkage
- // specified at the prior declaration.
- // FIXME. revisit this code.
- if (New->hasExternalStorage() &&
- Old->getLinkage() == InternalLinkage &&
- New->getDeclContext() == Old->getDeclContext())
- New->setStorageClass(Old->getStorageClass());
+
+ if (haveIncompatibleLanguageLinkages(Old, New)) {
+ Diag(New->getLocation(), diag::err_different_language_linkage) << New;
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ New->setInvalidDecl();
+ return;
+ }
+
+ // Merge "used" flag.
+ if (Old->isUsed(false))
+ New->setUsed();
// Keep a chain of previous declarations.
New->setPreviousDeclaration(Old);
@@ -2628,11 +2996,12 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
-/// no declarator (e.g. "struct foo;") is parsed. It also accopts template
+/// no declarator (e.g. "struct foo;") is parsed. It also accepts template
/// parameters to cope with template friend declarations.
Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DeclSpec &DS,
- MultiTemplateParamsArg TemplateParams) {
+ MultiTemplateParamsArg TemplateParams,
+ bool IsExplicitInstantiation) {
Decl *TagD = 0;
TagDecl *Tag = 0;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
@@ -2655,6 +3024,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
if (Tag) {
+ getASTContext().addUnnamedTag(Tag);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -2684,6 +3054,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return TagD;
}
+ DiagnoseFunctionSpecifiers(DS);
+
if (DS.isFriendSpecified()) {
// If we're dealing with a decl but not a TagDecl, assume that
// whatever routines created it handled the friendship aspect.
@@ -2692,10 +3064,28 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return ActOnFriendTypeDecl(S, DS, TemplateParams);
}
- // Track whether we warned about the fact that there aren't any
- // declarators.
- bool emittedWarning = false;
-
+ CXXScopeSpec &SS = DS.getTypeSpecScope();
+ bool IsExplicitSpecialization =
+ !TemplateParams.empty() && TemplateParams.back()->size() == 0;
+ if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
+ !IsExplicitInstantiation && !IsExplicitSpecialization) {
+ // 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.
+ // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
+ Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
+ << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
+ DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
+ DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
+ DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4)
+ << SS.getRange();
+ return 0;
+ }
+
+ // Track whether this decl-specifier declares anything.
+ bool DeclaresAnything = true;
+
+ // Handle anonymous struct definitions.
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
if (!Record->getDeclName() && Record->isCompleteDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
@@ -2703,13 +3093,11 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
Record->getDeclContext()->isRecord())
return BuildAnonymousStructOrUnion(S, DS, AS, Record);
- Diag(DS.getLocStart(), diag::ext_no_declarators)
- << DS.getSourceRange();
- emittedWarning = true;
+ DeclaresAnything = false;
}
}
- // Check for Microsoft C extension: anonymous struct.
+ // Check for Microsoft C extension: anonymous struct member.
if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus &&
CurContext->isRecord() &&
DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) {
@@ -2726,70 +3114,82 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return BuildMicrosoftCAnonymousStruct(S, DS, Record);
}
}
-
- if (getLangOpts().CPlusPlus &&
+
+ // Skip all the checks below if we have a type error.
+ if (DS.getTypeSpecType() == DeclSpec::TST_error ||
+ (TagD && TagD->isInvalidDecl()))
+ return TagD;
+
+ if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag))
if (Enum->enumerator_begin() == Enum->enumerator_end() &&
- !Enum->getIdentifier() && !Enum->isInvalidDecl()) {
- Diag(Enum->getLocation(), diag::ext_no_declarators)
- << DS.getSourceRange();
- emittedWarning = true;
- }
+ !Enum->getIdentifier() && !Enum->isInvalidDecl())
+ DeclaresAnything = false;
- // Skip all the checks below if we have a type error.
- if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD;
-
if (!DS.isMissingDeclaratorOk()) {
- // Warn about typedefs of enums without names, since this is an
- // extension in both Microsoft and GNU.
- if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef &&
- Tag && isa<EnumDecl>(Tag)) {
+ // Customize diagnostic for a typedef missing a name.
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
Diag(DS.getLocStart(), diag::ext_typedef_without_a_name)
<< DS.getSourceRange();
- return Tag;
- }
-
- Diag(DS.getLocStart(), diag::ext_no_declarators)
- << DS.getSourceRange();
- emittedWarning = true;
+ else
+ DeclaresAnything = false;
}
- // We're going to complain about a bunch of spurious specifiers;
- // only do this if we're declaring a tag, because otherwise we
- // should be getting diag::ext_no_declarators.
- if (emittedWarning || (TagD && TagD->isInvalidDecl()))
+ if (DS.isModulePrivateSpecified() &&
+ Tag && Tag->getDeclContext()->isFunctionOrMethod())
+ Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class)
+ << Tag->getTagKind()
+ << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc());
+
+ ActOnDocumentableDecl(TagD);
+
+ // C 6.7/2:
+ // A declaration [...] shall declare at least a declarator [...], a tag,
+ // or the members of an enumeration.
+ // C++ [dcl.dcl]p3:
+ // [If there are no declarators], and except for the declaration of an
+ // unnamed bit-field, the decl-specifier-seq shall introduce one or more
+ // names into the program, or shall redeclare a name introduced by a
+ // previous declaration.
+ if (!DeclaresAnything) {
+ // In C, we allow this as a (popular) extension / bug. Don't bother
+ // producing further diagnostics for redundant qualifiers after this.
+ Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange();
return TagD;
+ }
+
+ // C++ [dcl.stc]p1:
+ // If a storage-class-specifier appears in a decl-specifier-seq, [...] the
+ // init-declarator-list of the declaration shall not be empty.
+ // C++ [dcl.fct.spec]p1:
+ // If a cv-qualifier appears in a decl-specifier-seq, the
+ // init-declarator-list of the declaration shall not be empty.
+ //
+ // Spurious qualifiers here appear to be valid in C.
+ unsigned DiagID = diag::warn_standalone_specifier;
+ if (getLangOpts().CPlusPlus)
+ DiagID = diag::ext_standalone_specifier;
// Note that a linkage-specification sets a storage class, but
// 'extern "C" struct foo;' is actually valid and not theoretically
// useless.
- if (DeclSpec::SCS scs = DS.getStorageClassSpec())
- if (!DS.isExternInLinkageSpec())
- Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier)
- << DeclSpec::getSpecifierName(scs);
+ if (DeclSpec::SCS SCS = DS.getStorageClassSpec())
+ if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef)
+ Diag(DS.getStorageClassSpecLoc(), DiagID)
+ << DeclSpec::getSpecifierName(SCS);
if (DS.isThreadSpecified())
- Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread";
+ Diag(DS.getThreadSpecLoc(), DiagID) << "__thread";
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
- Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const";
+ Diag(DS.getConstSpecLoc(), DiagID) << "const";
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
- Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile";
+ Diag(DS.getConstSpecLoc(), DiagID) << "volatile";
// Restrict is covered above.
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
+ Diag(DS.getAtomicSpecLoc(), DiagID) << "_Atomic";
}
- if (DS.isInlineSpecified())
- Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline";
- if (DS.isVirtualSpecified())
- Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual";
- if (DS.isExplicitSpecified())
- Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit";
-
- if (DS.isModulePrivateSpecified() &&
- Tag && Tag->getDeclContext()->isFunctionOrMethod())
- Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class)
- << Tag->getTagKind()
- << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc());
// Warn about ignored type attributes, for example:
// __attribute__((aligned)) struct A;
@@ -2814,8 +3214,6 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
}
- ActOnDocumentableDecl(TagD);
-
return TagD;
}
@@ -2950,25 +3348,6 @@ StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
llvm_unreachable("unknown storage class specifier");
}
-/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to
-/// a StorageClass. Any error reporting is up to the caller:
-/// illegal input values are mapped to SC_None.
-static StorageClass
-StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
- switch (StorageClassSpec) {
- case DeclSpec::SCS_unspecified: return SC_None;
- case DeclSpec::SCS_extern: return SC_Extern;
- case DeclSpec::SCS_static: return SC_Static;
- case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
- // Illegal SCSs map to None: error reporting is up to the caller.
- case DeclSpec::SCS_auto: // Fall through.
- case DeclSpec::SCS_mutable: // Fall through.
- case DeclSpec::SCS_register: // Fall through.
- case DeclSpec::SCS_typedef: return SC_None;
- }
- llvm_unreachable("unknown storage class specifier");
-}
-
/// BuildAnonymousStructOrUnion - Handle the declaration of an
/// anonymous structure or union. Anonymous unions are a C++ feature
/// (C++ [class.union]) and a C11 feature; anonymous structures
@@ -3027,18 +3406,23 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified)
- << Record->isUnion() << 0
+ << Record->isUnion() << "const"
<< FixItHint::CreateRemoval(DS.getConstSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
- Diag(DS.getVolatileSpecLoc(),
+ Diag(DS.getVolatileSpecLoc(),
diag::ext_anonymous_struct_union_qualified)
- << Record->isUnion() << 1
+ << Record->isUnion() << "volatile"
<< FixItHint::CreateRemoval(DS.getVolatileSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
- Diag(DS.getRestrictSpecLoc(),
+ Diag(DS.getRestrictSpecLoc(),
diag::ext_anonymous_struct_union_qualified)
- << Record->isUnion() << 2
+ << Record->isUnion() << "restrict"
<< FixItHint::CreateRemoval(DS.getRestrictSpecLoc());
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
+ Diag(DS.getAtomicSpecLoc(),
+ diag::ext_anonymous_struct_union_qualified)
+ << Record->isUnion() << "_Atomic"
+ << FixItHint::CreateRemoval(DS.getAtomicSpecLoc());
DS.ClearTypeQualifiers();
}
@@ -3088,6 +3472,13 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
<< (int)Record->isUnion();
Invalid = true;
}
+ } else {
+ // This is an anonymous type definition within another anonymous type.
+ // This is a popular extension, provided by Plan9, MSVC and GCC, but
+ // not part of standard C++.
+ Diag(MemRecord->getLocation(),
+ diag::ext_anonymous_record_with_anonymous_type)
+ << (int)Record->isUnion();
}
} else if (isa<AccessSpecDecl>(*Mem)) {
// Any access specifier is fine.
@@ -3153,15 +3544,12 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Invalid = true;
SC = SC_None;
}
- SCSpec = DS.getStorageClassSpecAsWritten();
- VarDecl::StorageClass SCAsWritten
- = StorageClassSpecToVarDeclStorageClass(SCSpec);
Anon = VarDecl::Create(Context, Owner,
DS.getLocStart(),
Record->getLocation(), /*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
- TInfo, SC, SCAsWritten);
+ TInfo, SC);
// Default-initialize the implicit variable. This initialization will be
// trivial in almost all cases, except if a union member has an in-class
@@ -3383,7 +3771,7 @@ static QualType getCoreType(QualType Ty) {
static bool hasSimilarParameters(ASTContext &Context,
FunctionDecl *Declaration,
FunctionDecl *Definition,
- llvm::SmallVectorImpl<unsigned> &Params) {
+ SmallVectorImpl<unsigned> &Params) {
Params.clear();
if (Declaration->param_size() != Definition->param_size())
return false;
@@ -3609,8 +3997,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
return false;
}
-Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
- MultiTemplateParamsArg TemplateParamLists) {
+NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists) {
// TODO: consider using NameInfo for diagnostic.
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
@@ -3690,8 +4078,6 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
return 0;
- NamedDecl *New;
-
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
@@ -3776,6 +4162,13 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
Previous.clear();
+ // Check that there are no default arguments other than in the parameters
+ // of a function declaration (C++ only).
+ if (getLangOpts().CPlusPlus)
+ CheckExtraCXXDefaultArguments(D);
+
+ NamedDecl *New;
+
bool AddToScope = true;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
if (TemplateParamLists.size()) {
@@ -3877,29 +4270,29 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
static void
FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) {
- if (PointerTypeLoc* SrcPTL = dyn_cast<PointerTypeLoc>(&SrcTL)) {
- PointerTypeLoc* DstPTL = cast<PointerTypeLoc>(&DstTL);
- FixInvalidVariablyModifiedTypeLoc(SrcPTL->getPointeeLoc(),
- DstPTL->getPointeeLoc());
- DstPTL->setStarLoc(SrcPTL->getStarLoc());
+ if (PointerTypeLoc SrcPTL = SrcTL.getAs<PointerTypeLoc>()) {
+ PointerTypeLoc DstPTL = DstTL.castAs<PointerTypeLoc>();
+ FixInvalidVariablyModifiedTypeLoc(SrcPTL.getPointeeLoc(),
+ DstPTL.getPointeeLoc());
+ DstPTL.setStarLoc(SrcPTL.getStarLoc());
return;
}
- if (ParenTypeLoc* SrcPTL = dyn_cast<ParenTypeLoc>(&SrcTL)) {
- ParenTypeLoc* DstPTL = cast<ParenTypeLoc>(&DstTL);
- FixInvalidVariablyModifiedTypeLoc(SrcPTL->getInnerLoc(),
- DstPTL->getInnerLoc());
- DstPTL->setLParenLoc(SrcPTL->getLParenLoc());
- DstPTL->setRParenLoc(SrcPTL->getRParenLoc());
+ if (ParenTypeLoc SrcPTL = SrcTL.getAs<ParenTypeLoc>()) {
+ ParenTypeLoc DstPTL = DstTL.castAs<ParenTypeLoc>();
+ FixInvalidVariablyModifiedTypeLoc(SrcPTL.getInnerLoc(),
+ DstPTL.getInnerLoc());
+ DstPTL.setLParenLoc(SrcPTL.getLParenLoc());
+ DstPTL.setRParenLoc(SrcPTL.getRParenLoc());
return;
}
- ArrayTypeLoc* SrcATL = cast<ArrayTypeLoc>(&SrcTL);
- ArrayTypeLoc* DstATL = cast<ArrayTypeLoc>(&DstTL);
- TypeLoc SrcElemTL = SrcATL->getElementLoc();
- TypeLoc DstElemTL = DstATL->getElementLoc();
+ ArrayTypeLoc SrcATL = SrcTL.castAs<ArrayTypeLoc>();
+ ArrayTypeLoc DstATL = DstTL.castAs<ArrayTypeLoc>();
+ TypeLoc SrcElemTL = SrcATL.getElementLoc();
+ TypeLoc DstElemTL = DstATL.getElementLoc();
DstElemTL.initializeFullCopy(SrcElemTL);
- DstATL->setLBracketLoc(SrcATL->getLBracketLoc());
- DstATL->setSizeExpr(SrcATL->getSizeExpr());
- DstATL->setRBracketLoc(SrcATL->getRBracketLoc());
+ DstATL.setLBracketLoc(SrcATL.getLBracketLoc());
+ DstATL.setSizeExpr(SrcATL.getSizeExpr());
+ DstATL.setRBracketLoc(SrcATL.getRBracketLoc());
}
/// Helper method to turn variable array types into constant array
@@ -3921,7 +4314,7 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
return FixedTInfo;
}
-/// \brief Register the given locally-scoped external C declaration so
+/// \brief Register the given locally-scoped extern "C" declaration so
/// that it can be found later for redeclarations
void
Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
@@ -3930,15 +4323,15 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
"Decl is not a locally-scoped decl!");
// Note that we have a locally-scoped external with this name.
- LocallyScopedExternalDecls[ND->getDeclName()] = ND;
+ LocallyScopedExternCDecls[ND->getDeclName()] = ND;
if (!Previous.isSingleResult())
return;
NamedDecl *PrevDecl = Previous.getFoundDecl();
- // If there was a previous declaration of this variable, it may be
- // in our identifier chain. Update the identifier chain with the new
+ // If there was a previous declaration of this entity, it may be in
+ // our identifier chain. Update the identifier chain with the new
// declaration.
if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) {
// The previous declaration was found on the identifer resolver
@@ -3962,38 +4355,42 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
}
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
-Sema::findLocallyScopedExternalDecl(DeclarationName Name) {
+Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
if (ExternalSource) {
// Load locally-scoped external decls from the external source.
SmallVector<NamedDecl *, 4> Decls;
- ExternalSource->ReadLocallyScopedExternalDecls(Decls);
+ ExternalSource->ReadLocallyScopedExternCDecls(Decls);
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = LocallyScopedExternalDecls.find(Decls[I]->getDeclName());
- if (Pos == LocallyScopedExternalDecls.end())
- LocallyScopedExternalDecls[Decls[I]->getDeclName()] = Decls[I];
+ = LocallyScopedExternCDecls.find(Decls[I]->getDeclName());
+ if (Pos == LocallyScopedExternCDecls.end())
+ LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I];
}
}
- return LocallyScopedExternalDecls.find(Name);
+ return LocallyScopedExternCDecls.find(Name);
}
/// \brief Diagnose function specifiers on a declaration of an identifier that
/// does not identify a function.
-void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
+void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) {
// FIXME: We should probably indicate the identifier in question to avoid
// confusion for constructs like "inline int a(), b;"
- if (D.getDeclSpec().isInlineSpecified())
- Diag(D.getDeclSpec().getInlineSpecLoc(),
+ if (DS.isInlineSpecified())
+ Diag(DS.getInlineSpecLoc(),
diag::err_inline_non_function);
- if (D.getDeclSpec().isVirtualSpecified())
- Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ if (DS.isVirtualSpecified())
+ Diag(DS.getVirtualSpecLoc(),
diag::err_virtual_non_function);
- if (D.getDeclSpec().isExplicitSpecified())
- Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ if (DS.isExplicitSpecified())
+ Diag(DS.getExplicitSpecLoc(),
diag::err_explicit_non_function);
+
+ if (DS.isNoreturnSpecified())
+ Diag(DS.getNoreturnSpecLoc(),
+ diag::err_noreturn_non_function);
}
NamedDecl*
@@ -4009,12 +4406,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Previous.clear();
}
- if (getLangOpts().CPlusPlus) {
- // Check that there are no default arguments (C++ only).
- CheckExtraCXXDefaultArguments(D);
- }
-
- DiagnoseFunctionSpecifiers(D);
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
@@ -4090,6 +4482,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
// in an outer scope, it isn't the same thing.
FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,
/*ExplicitInstantiationOrSpecialization=*/false);
+ filterNonConflictingPreviousDecls(Context, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
MergeTypedefNameDecl(NewTD, Previous);
@@ -4220,6 +4613,74 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
return false;
}
+static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
+ // 'weak' only applies to declarations with external linkage.
+ if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) {
+ if (ND.getLinkage() != ExternalLinkage) {
+ S.Diag(Attr->getLocation(), diag::err_attribute_weak_static);
+ ND.dropAttr<WeakAttr>();
+ }
+ }
+ if (WeakRefAttr *Attr = ND.getAttr<WeakRefAttr>()) {
+ if (ND.hasExternalLinkage()) {
+ S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static);
+ ND.dropAttr<WeakRefAttr>();
+ }
+ }
+}
+
+/// Given that we are within the definition of the given function,
+/// will that definition behave like C99's 'inline', where the
+/// definition is discarded except for optimization purposes?
+static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
+ // Try to avoid calling GetGVALinkageForFunction.
+
+ // All cases of this require the 'inline' keyword.
+ if (!FD->isInlined()) return false;
+
+ // This is only possible in C++ with the gnu_inline attribute.
+ if (S.getLangOpts().CPlusPlus && !FD->hasAttr<GNUInlineAttr>())
+ return false;
+
+ // Okay, go ahead and call the relatively-more-expensive function.
+
+#ifndef NDEBUG
+ // AST quite reasonably asserts that it's working on a function
+ // definition. We don't really have a way to tell it that we're
+ // currently defining the function, so just lie to it in +Asserts
+ // builds. This is an awful hack.
+ FD->setLazyBody(1);
+#endif
+
+ bool isC99Inline = (S.Context.GetGVALinkageForFunction(FD) == GVA_C99Inline);
+
+#ifndef NDEBUG
+ FD->setLazyBody(0);
+#endif
+
+ return isC99Inline;
+}
+
+static bool shouldConsiderLinkage(const VarDecl *VD) {
+ const DeclContext *DC = VD->getDeclContext()->getRedeclContext();
+ if (DC->isFunctionOrMethod())
+ return VD->hasExternalStorage();
+ if (DC->isFileContext())
+ return true;
+ if (DC->isRecord())
+ return false;
+ llvm_unreachable("Unexpected context");
+}
+
+static bool shouldConsiderLinkage(const FunctionDecl *FD) {
+ const DeclContext *DC = FD->getDeclContext()->getRedeclContext();
+ if (DC->isFileContext() || DC->isFunctionOrMethod())
+ return true;
+ if (DC->isRecord())
+ return false;
+ llvm_unreachable("Unexpected context");
+}
+
NamedDecl*
Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -4227,14 +4688,21 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
QualType R = TInfo->getType();
DeclarationName Name = GetNameForDeclarator(D).getName();
- // Check that there are no default arguments (C++ only).
- if (getLangOpts().CPlusPlus)
- CheckExtraCXXDefaultArguments(D);
-
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
assert(SCSpec != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class VarDecl.");
VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+
+ if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16)
+ {
+ // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
+ // half array type (unless the cl_khr_fp16 extension is enabled).
+ if (Context.getBaseElementType(R)->isHalfType()) {
+ Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
+ D.setInvalidType();
+ }
+ }
+
if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
@@ -4242,9 +4710,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
D.setInvalidType();
SC = SC_None;
}
- SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
- VarDecl::StorageClass SCAsWritten
- = StorageClassSpecToVarDeclStorageClass(SCSpec);
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (!II) {
@@ -4253,7 +4718,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
return 0;
}
- DiagnoseFunctionSpecifiers(D);
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (!DC->isRecord() && S->getFnParent() == 0) {
// C99 6.9p2: The storage-class specifiers auto and register shall not
@@ -4273,8 +4738,33 @@ 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)
+ 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.
+ if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local ||
+ R.getAddressSpace() == LangAS::opencl_global)) {
+ Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
+ }
+
+ // OpenCL 1.2 spec, p6.9 r:
+ // The event type cannot be used to declare a program scope variable.
+ // The event type cannot be used with the __local, __constant and __global
+ // address space qualifiers.
+ if (R->isEventT()) {
+ if (S->getParent() == 0) {
+ Diag(D.getLocStart(), diag::err_event_t_global_var);
+ D.setInvalidType();
+ }
+
+ if (R.getAddressSpace()) {
+ Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
+ D.setInvalidType();
+ }
+ }
}
bool isExplicitSpecialization = false;
@@ -4282,7 +4772,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!getLangOpts().CPlusPlus) {
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
- R, TInfo, SC, SCAsWritten);
+ R, TInfo, SC);
if (D.isInvalidType())
NewVD->setInvalidDecl();
@@ -4293,8 +4783,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
- } else if (SC == SC_None)
- SC = SC_Static;
+ }
}
if (SC == SC_Static && CurContext->isRecord()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
@@ -4307,7 +4796,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// the program is ill-formed. C++11 drops this restriction.
if (RD->isUnion())
Diag(D.getIdentifierLoc(),
- getLangOpts().CPlusPlus0x
+ getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_static_data_member_in_union
: diag::ext_static_data_member_in_union) << Name;
// We conservatively disallow static data members in anonymous structs.
@@ -4352,7 +4841,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
- R, TInfo, SC, SCAsWritten);
+ R, TInfo, SC);
// If this decl has an auto type in need of deduction, make a note of the
// Decl so we can diagnose uses of it in its own initializer.
@@ -4388,6 +4877,25 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setThreadSpecified(true);
}
+ // C99 6.7.4p3
+ // An inline definition of a function with external linkage shall
+ // not contain a definition of a modifiable object with static or
+ // thread storage duration...
+ // We only apply this when the function is required to be defined
+ // elsewhere, i.e. when the function is not 'extern inline'. Note
+ // that a local variable with thread storage duration still has to
+ // be marked 'static'. Also note that it's possible to get these
+ // semantics in C++ using __attribute__((gnu_inline)).
+ if (SC == SC_Static && S->getFnParent() != 0 &&
+ !NewVD->getType().isConstQualified()) {
+ FunctionDecl *CurFD = getCurFunctionDecl();
+ if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) {
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::warn_static_local_in_extern_inline);
+ MaybeSuggestAddingStaticToDecl(CurFD);
+ }
+ }
+
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (isExplicitSpecialization)
Diag(NewVD->getLocation(), diag::err_module_private_specialization)
@@ -4405,12 +4913,17 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewVD, D);
+ if (NewVD->hasAttrs())
+ CheckAlignasUnderalignment(NewVD);
+
if (getLangOpts().CUDA) {
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
// storage [duration]."
if (SC == SC_None && S->getFnParent() != 0 &&
- (NewVD->hasAttr<CUDASharedAttr>() || NewVD->hasAttr<CUDAConstantAttr>()))
+ (NewVD->hasAttr<CUDASharedAttr>() ||
+ NewVD->hasAttr<CUDAConstantAttr>())) {
NewVD->setStorageClass(SC_Static);
+ }
}
// In auto-retain/release, infer strong retension for variables of
@@ -4459,7 +4972,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Don't consider existing declarations that are in a different
// scope and are out-of-semantic-context declarations (if the new
// declaration has linkage).
- FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(),
+ FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewVD),
isExplicitSpecialization);
if (!getLangOpts().CPlusPlus) {
@@ -4493,19 +5006,15 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setInvalidDecl();
}
+ ProcessPragmaWeak(S, NewVD);
+ checkAttributesAfterMerging(*this, *NewVD);
+
// If this is a locally-scoped extern C variable, update the map of
// such variables.
if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
!NewVD->isInvalidDecl())
RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
- // If there's a #pragma GCC visibility in scope, and this isn't a class
- // member, set the visibility of this variable.
- if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord())
- AddPushedVisibilityAttribute(NewVD);
-
- MarkUnusedFileScopedDecl(NewVD);
-
return NewVD;
}
@@ -4604,6 +5113,32 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
CheckShadow(S, D, R);
}
+template<typename T>
+static bool mayConflictWithNonVisibleExternC(const T *ND) {
+ const DeclContext *DC = ND->getDeclContext();
+ if (DC->getRedeclContext()->isTranslationUnit())
+ return true;
+
+ // We know that is the first decl we see, other than function local
+ // extern C ones. If this is C++ and the decl is not in a extern C context
+ // it cannot have C language linkage. Avoid calling isExternC in that case.
+ // We need to this because of code like
+ //
+ // namespace { struct bar {}; }
+ // auto foo = bar();
+ //
+ // This code runs before the init of foo is set, and therefore before
+ // the type of foo is known. Not knowing the type we cannot know its linkage
+ // unless it is in an extern C block.
+ if (!DC->isExternCContext()) {
+ const ASTContext &Context = ND->getASTContext();
+ if (Context.getLangOpts().CPlusPlus)
+ return false;
+ }
+
+ return ND->isExternC();
+}
+
/// \brief Perform semantic checking on a newly-created variable
/// declaration.
///
@@ -4706,16 +5241,44 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
NewVD->setTypeSourceInfo(FixedTInfo);
}
- if (Previous.empty() && NewVD->isExternC()) {
- // Since we did not find anything by this name and we're declaring
- // an extern "C" variable, look for a non-visible extern "C"
- // declaration with the same name.
+ // If we did not find anything by this name, look for a non-visible
+ // extern "C" declaration with the same name.
+ //
+ // Clang has a lot of problems with extern local declarations.
+ // The actual standards text here is:
+ //
+ // C++11 [basic.link]p6:
+ // The name of a function declared in block scope and the name
+ // of a variable declared by a block scope extern declaration
+ // have linkage. If there is a visible declaration of an entity
+ // with linkage having the same name and type, ignoring entities
+ // declared outside the innermost enclosing namespace scope, the
+ // block scope declaration declares that same entity and
+ // receives the linkage of the previous declaration.
+ //
+ // C11 6.2.7p4:
+ // For an identifier with internal or external linkage declared
+ // in a scope in which a prior declaration of that identifier is
+ // visible, if the prior declaration specifies internal or
+ // external linkage, the type of the identifier at the later
+ // declaration becomes the composite type.
+ //
+ // The most important point here is that we're not allowed to
+ // update our understanding of the type according to declarations
+ // not in scope.
+ bool PreviousWasHidden = false;
+ if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) {
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternalDecl(NewVD->getDeclName());
- if (Pos != LocallyScopedExternalDecls.end())
+ = findLocallyScopedExternCDecl(NewVD->getDeclName());
+ if (Pos != LocallyScopedExternCDecls.end()) {
Previous.addDecl(Pos->second);
+ PreviousWasHidden = true;
+ }
}
+ // Filter out any non-conflicting previous declarations.
+ filterNonConflictingPreviousDecls(Context, NewVD, Previous);
+
if (T->isVoidType() && !NewVD->hasExternalStorage()) {
Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
<< T;
@@ -4743,7 +5306,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
}
if (!Previous.empty()) {
- MergeVarDecl(NewVD, Previous);
+ MergeVarDecl(NewVD, Previous, PreviousWasHidden);
return true;
}
return false;
@@ -4778,9 +5341,9 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
}
for (Path.Decls = BaseRecord->lookup(Name);
- Path.Decls.first != Path.Decls.second;
- ++Path.Decls.first) {
- NamedDecl *D = *Path.Decls.first;
+ !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;
@@ -4832,6 +5395,7 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
+ !CheckOverridingFunctionAttributes(MD, OldMD) &&
!CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
!CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
hasDeletedOverridenMethods |= OldMD->isDeleted();
@@ -4878,7 +5442,7 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
if (candidate.getEditDistance() == 0)
return false;
- llvm::SmallVector<unsigned, 1> MismatchedParams;
+ SmallVector<unsigned, 1> MismatchedParams;
for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(),
CDeclEnd = candidate.end();
CDecl != CDeclEnd; ++CDecl) {
@@ -4924,8 +5488,8 @@ static NamedDecl* DiagnoseInvalidRedeclaration(
DeclContext *NewDC = NewFD->getDeclContext();
LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
- llvm::SmallVector<unsigned, 1> MismatchedParams;
- llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1> NearMatches;
+ SmallVector<unsigned, 1> MismatchedParams;
+ SmallVector<std::pair<FunctionDecl *, unsigned>, 1> NearMatches;
TypoCorrection Correction;
bool isFriendDecl = (SemaRef.getLangOpts().CPlusPlus &&
ExtraArgs.D.getDeclSpec().isFriendSpecified());
@@ -5029,7 +5593,7 @@ static NamedDecl* DiagnoseInvalidRedeclaration(
if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
NewFDisConst = NewMD->isConst();
- for (llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1>::iterator
+ for (SmallVector<std::pair<FunctionDecl *, unsigned>, 1>::iterator
NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end();
NearMatch != NearMatchEnd; ++NearMatch) {
FunctionDecl *FD = NearMatch->first;
@@ -5098,9 +5662,6 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
FunctionDecl *NewFD = 0;
bool isInline = D.getDeclSpec().isInlineSpecified();
- DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
- FunctionDecl::StorageClass SCAsWritten
- = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
if (!SemaRef.getLangOpts().CPlusPlus) {
// Determine whether the function was written with a
@@ -5114,8 +5675,8 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
NewFD = FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(), NameInfo, R,
- TInfo, SC, SCAsWritten, isInline,
- HasPrototype);
+ TInfo, SC, isInline,
+ HasPrototype, false);
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -5164,7 +5725,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
// If the class is complete, then we now create the implicit exception
// specification. If the class is incomplete or dependent, we can't do
// it yet.
- if (SemaRef.getLangOpts().CPlusPlus0x && !Record->isDependentType() &&
+ if (SemaRef.getLangOpts().CPlusPlus11 && !Record->isDependentType() &&
Record->getDefinition() && !Record->isBeingDefined() &&
R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) {
SemaRef.AdjustDestructorExceptionSpec(Record, NewDD);
@@ -5182,7 +5743,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
return FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(),
D.getIdentifierLoc(), Name, R, TInfo,
- SC, SCAsWritten, isInline,
+ SC, isInline,
/*hasPrototype=*/true, isConstexpr);
}
@@ -5213,36 +5774,21 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
return 0;
}
- bool isStatic = SC == SC_Static;
-
- // [class.free]p1:
- // Any allocation function for a class T is a static member
- // (even if not explicitly declared static).
- if (Name.getCXXOverloadedOperator() == OO_New ||
- Name.getCXXOverloadedOperator() == OO_Array_New)
- isStatic = true;
-
- // [class.free]p6 Any deallocation function for a class X is a static member
- // (even if not explicitly declared static).
- if (Name.getCXXOverloadedOperator() == OO_Delete ||
- Name.getCXXOverloadedOperator() == OO_Array_Delete)
- isStatic = true;
-
- IsVirtualOkay = !isStatic;
-
// This is a C++ method declaration.
- return CXXMethodDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
- D.getLocStart(), NameInfo, R,
- TInfo, isStatic, SCAsWritten, isInline,
- isConstexpr, SourceLocation());
-
+ CXXMethodDecl *Ret = CXXMethodDecl::Create(SemaRef.Context,
+ cast<CXXRecordDecl>(DC),
+ D.getLocStart(), NameInfo, R,
+ TInfo, SC, isInline,
+ isConstexpr, SourceLocation());
+ IsVirtualOkay = !Ret->isStatic();
+ return Ret;
} else {
// Determine whether the function was written with a
// prototype. This true when:
// - we're in C++ (where every function has a prototype),
return FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(),
- NameInfo, R, TInfo, SC, SCAsWritten, isInline,
+ NameInfo, R, TInfo, SC, isInline,
true/*HasPrototype*/, isConstexpr);
}
}
@@ -5291,8 +5837,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
T = Context.getObjCObjectPointerType(T);
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- R = Context.getFunctionType(T, FPT->arg_type_begin(),
- FPT->getNumArgs(), EPI);
+ R = Context.getFunctionType(T,
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI);
}
else if (isa<FunctionNoProtoType>(R))
R = Context.getFunctionNoProtoType(T);
@@ -5504,11 +6052,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
if (isConstexpr) {
- // C++0x [dcl.constexpr]p2: constexpr functions and constexpr constructors
+ // C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors
// are implicitly inline.
NewFD->setImplicitlyInline();
- // C++0x [dcl.constexpr]p3: functions declared constexpr are required to
+ // C++11 [dcl.constexpr]p3: functions declared constexpr are required to
// be either constructors or to return a literal type. Therefore,
// destructors cannot be declared constexpr.
if (isa<CXXDestructorDecl>(NewFD))
@@ -5583,17 +6131,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
const FunctionProtoType *FPT = R->getAs<FunctionProtoType>();
if ((Name.getCXXOverloadedOperator() == OO_Delete ||
Name.getCXXOverloadedOperator() == OO_Array_Delete) &&
- getLangOpts().CPlusPlus0x && FPT && !FPT->hasExceptionSpec()) {
+ getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpecType = EST_BasicNoexcept;
NewFD->setType(Context.getFunctionType(FPT->getResultType(),
- FPT->arg_type_begin(),
- FPT->getNumArgs(), EPI));
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI));
}
}
// Filter out previous declarations that don't match the scope.
- FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(),
+ FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewFD),
isExplicitSpecialization ||
isFunctionTemplateSpecialization);
@@ -5675,6 +6224,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope);
DeclsInPrototypeScope.clear();
+ if (D.getDeclSpec().isNoreturnSpecified())
+ NewFD->addAttr(
+ ::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
+ Context));
+
// Process the non-inheritable attributes on this declaration.
ProcessDeclAttributes(S, NewFD, D,
/*NonInheritable=*/true, /*Inheritable=*/false);
@@ -5691,6 +6245,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
ProcessDeclAttributes(S, NewFD, D,
/*NonInheritable=*/false, /*Inheritable=*/true);
+ QualType RetType = NewFD->getResultType();
+ const CXXRecordDecl *Ret = RetType->isRecordType() ?
+ RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl();
+ if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() &&
+ Ret && Ret->hasAttr<WarnUnusedResultAttr>()) {
+ const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+ if (!(MD && MD->getCorrespondingMethodInClass(Ret, true))) {
+ NewFD->addAttr(new (Context) WarnUnusedResultAttr(SourceRange(),
+ Context));
+ }
+ }
+
if (!getLangOpts().CPlusPlus) {
// Perform semantic checking on the function declaration.
bool isExplicitSpecialization=false;
@@ -5788,7 +6354,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// A storage-class-specifier shall not be specified in an explicit
// specialization (14.7.3)
if (SC != SC_None) {
- if (SC != NewFD->getStorageClass())
+ if (SC != NewFD->getTemplateSpecializationInfo()->getTemplate()->getTemplatedDecl()->getStorageClass())
Diag(NewFD->getLocation(),
diag::err_explicit_specialization_inconsistent_storage_class)
<< SC
@@ -5938,6 +6504,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ ProcessPragmaWeak(S, NewFD);
+ checkAttributesAfterMerging(*this, *NewFD);
+
AddKnownFunctionAttributes(NewFD);
if (NewFD->hasAttr<OverloadableAttr>() &&
@@ -5952,13 +6521,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
EPI.Variadic = true;
EPI.ExtInfo = FT->getExtInfo();
- QualType R = Context.getFunctionType(FT->getResultType(), 0, 0, EPI);
+ QualType R = Context.getFunctionType(FT->getResultType(),
+ ArrayRef<QualType>(),
+ EPI);
NewFD->setType(R);
}
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this function.
- if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord())
+ if (!DC->isRecord() && NewFD->hasExternalLinkage())
AddPushedVisibilityAttribute(NewFD);
// If there's a #pragma clang arc_cf_code_audited in scope, consider
@@ -5982,12 +6553,42 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- // OpenCL v1.2 s6.8 static is invalid for kernel functions.
- if ((getLangOpts().OpenCLVersion >= 120)
- && NewFD->hasAttr<OpenCLKernelAttr>()
- && (SC == SC_Static)) {
- Diag(D.getIdentifierLoc(), diag::err_static_kernel);
- D.setInvalidType();
+ if (NewFD->hasAttr<OpenCLKernelAttr>()) {
+ // OpenCL v1.2 s6.8 static is invalid for kernel functions.
+ if ((getLangOpts().OpenCLVersion >= 120)
+ && (SC == SC_Static)) {
+ Diag(D.getIdentifierLoc(), diag::err_static_kernel);
+ D.setInvalidType();
+ }
+
+ // OpenCL v1.2, s6.9 -- Kernels can only have return type void.
+ if (!NewFD->getResultType()->isVoidType()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_expected_kernel_void_return_type);
+ D.setInvalidType();
+ }
+
+ for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
+ PE = NewFD->param_end(); PI != PE; ++PI) {
+ ParmVarDecl *Param = *PI;
+ QualType PT = Param->getType();
+
+ // OpenCL v1.2 s6.9.a:
+ // A kernel function argument cannot be declared as a
+ // pointer to a pointer type.
+ if (PT->isPointerType() && PT->getPointeeType()->isPointerType()) {
+ Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_arg);
+ D.setInvalidType();
+ }
+
+ // OpenCL v1.2 s6.8 n:
+ // A kernel function argument cannot be declared
+ // of event_t type.
+ if (PT->isEventT()) {
+ Diag(Param->getLocation(), diag::err_event_t_kernel_arg);
+ D.setInvalidType();
+ }
+ }
}
MarkUnusedFileScopedDecl(NewFD);
@@ -6043,17 +6644,20 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
&& "Variably modified return types are not handled here");
// Check for a previous declaration of this name.
- if (Previous.empty() && NewFD->isExternC()) {
- // Since we did not find anything by this name and we're declaring
- // an extern "C" function, look for a non-visible extern "C"
- // declaration with the same name.
+ if (Previous.empty() && mayConflictWithNonVisibleExternC(NewFD)) {
+ // Since we did not find anything by this name, look for a non-visible
+ // extern "C" declaration with the same name.
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternalDecl(NewFD->getDeclName());
- if (Pos != LocallyScopedExternalDecls.end())
+ = findLocallyScopedExternCDecl(NewFD->getDeclName());
+ if (Pos != LocallyScopedExternCDecls.end())
Previous.addDecl(Pos->second);
}
+ // Filter out any non-conflicting previous declarations.
+ filterNonConflictingPreviousDecls(Context, NewFD, Previous);
+
bool Redeclaration = false;
+ NamedDecl *OldDecl = 0;
// Merge or overload the declaration with an existing declaration of
// the same name, if appropriate.
@@ -6062,8 +6666,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// a declaration that requires merging. If it's an overload,
// there's no more work to do here; we'll just add the new
// function to the scope.
-
- NamedDecl *OldDecl = 0;
if (!AllowOverloadingOfFunction(Previous, Context)) {
Redeclaration = true;
OldDecl = Previous.getFoundDecl();
@@ -6100,42 +6702,90 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Context));
}
}
+ }
- if (Redeclaration) {
- // NewFD and OldDecl represent declarations that need to be
- // merged.
- if (MergeFunctionDecl(NewFD, OldDecl, S)) {
- NewFD->setInvalidDecl();
- return Redeclaration;
- }
+ // C++11 [dcl.constexpr]p8:
+ // A constexpr specifier for a non-static member function that is not
+ // a constructor declares that member function to be const.
+ //
+ // This needs to be delayed until we know whether this is an out-of-line
+ // definition of a static member function.
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+ if (MD && MD->isConstexpr() && !MD->isStatic() &&
+ !isa<CXXConstructorDecl>(MD) &&
+ (MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
+ CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl);
+ if (FunctionTemplateDecl *OldTD =
+ dyn_cast_or_null<FunctionTemplateDecl>(OldDecl))
+ OldMD = dyn_cast<CXXMethodDecl>(OldTD->getTemplatedDecl());
+ if (!OldMD || !OldMD->isStatic()) {
+ const FunctionProtoType *FPT =
+ MD->getType()->castAs<FunctionProtoType>();
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.TypeQuals |= Qualifiers::Const;
+ MD->setType(Context.getFunctionType(FPT->getResultType(),
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI));
+ }
+ }
- Previous.clear();
- Previous.addDecl(OldDecl);
-
- if (FunctionTemplateDecl *OldTemplateDecl
- = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
- NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
- FunctionTemplateDecl *NewTemplateDecl
- = NewFD->getDescribedFunctionTemplate();
- assert(NewTemplateDecl && "Template/non-template mismatch");
- if (CXXMethodDecl *Method
- = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
- Method->setAccess(OldTemplateDecl->getAccess());
- NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
- }
-
- // If this is an explicit specialization of a member that is a function
- // template, mark it as a member specialization.
- if (IsExplicitSpecialization &&
- NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
- NewTemplateDecl->setMemberSpecialization();
- assert(OldTemplateDecl->isMemberSpecialization());
+ if (Redeclaration) {
+ // NewFD and OldDecl represent declarations that need to be
+ // merged.
+ if (MergeFunctionDecl(NewFD, OldDecl, S)) {
+ NewFD->setInvalidDecl();
+ return Redeclaration;
+ }
+
+ Previous.clear();
+ Previous.addDecl(OldDecl);
+
+ if (FunctionTemplateDecl *OldTemplateDecl
+ = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
+ NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+ FunctionTemplateDecl *NewTemplateDecl
+ = NewFD->getDescribedFunctionTemplate();
+ assert(NewTemplateDecl && "Template/non-template mismatch");
+ if (CXXMethodDecl *Method
+ = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
+ Method->setAccess(OldTemplateDecl->getAccess());
+ NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
+ }
+
+ // If this is an explicit specialization of a member that is a function
+ // template, mark it as a member specialization.
+ if (IsExplicitSpecialization &&
+ NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
+ NewTemplateDecl->setMemberSpecialization();
+ assert(OldTemplateDecl->isMemberSpecialization());
+ }
+
+ } else {
+ // This needs to happen first so that 'inline' propagates.
+ NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+
+ if (isa<CXXMethodDecl>(NewFD)) {
+ // A valid redeclaration of a C++ method must be out-of-line,
+ // but (unfortunately) it's not necessarily a definition
+ // because of templates, which means that the previous
+ // declaration is not necessarily from the class definition.
+
+ // For just setting the access, that doesn't matter.
+ CXXMethodDecl *oldMethod = cast<CXXMethodDecl>(OldDecl);
+ NewFD->setAccess(oldMethod->getAccess());
+
+ // Update the key-function state if necessary for this ABI.
+ if (NewFD->isInlined() &&
+ !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
+ // setNonKeyFunction needs to work with the original
+ // declaration from the class definition, and isVirtual() is
+ // just faster in that case, so map back to that now.
+ oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDeclaration());
+ if (oldMethod->isVirtual()) {
+ Context.setNonKeyFunction(oldMethod);
+ }
}
-
- } else {
- if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
- NewFD->setAccess(OldDecl->getAccess());
- NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
}
}
}
@@ -6208,6 +6858,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// declaration against the expected type for the builtin.
if (unsigned BuiltinID = NewFD->getBuiltinID()) {
ASTContext::GetBuiltinTypeError Error;
+ LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
QualType T = Context.GetBuiltinType(BuiltinID, Error);
if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
// The type of this function differs from the type of the builtin,
@@ -6219,7 +6870,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// If this function is declared as being extern "C", then check to see if
// the function returns a UDT (class, struct, or union type) that is not C
// compatible, and if it does, warn the user.
- if (NewFD->isExternC()) {
+ // But, issue any diagnostic on the first declaration only.
+ if (NewFD->isExternC() && Previous.empty()) {
QualType R = NewFD->getResultType();
if (R->isIncompleteType() && !R->isVoidType())
Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete)
@@ -6232,12 +6884,30 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
return Redeclaration;
}
+static SourceRange getResultSourceRange(const FunctionDecl *FD) {
+ const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
+ if (!TSI)
+ return SourceRange();
+
+ TypeLoc TL = TSI->getTypeLoc();
+ FunctionTypeLoc FunctionTL = TL.getAs<FunctionTypeLoc>();
+ if (!FunctionTL)
+ return SourceRange();
+
+ TypeLoc ResultTL = FunctionTL.getResultLoc();
+ if (ResultTL.getUnqualifiedLoc().getAs<BuiltinTypeLoc>())
+ return ResultTL.getSourceRange();
+
+ return SourceRange();
+}
+
void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
// C++11 [basic.start.main]p3: A program that declares main to be inline,
// static or constexpr is ill-formed.
- // C99 6.7.4p4: In a hosted environment, the inline function specifier
- // shall not appear in a declaration of main.
+ // C11 6.7.4p4: In a hosted environment, no function specifier(s) shall
+ // appear in a declaration of main.
// static main is not an error under C99, but we should warn about it.
+ // We accept _Noreturn main as an extension.
if (FD->getStorageClass() == SC_Static)
Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus
? diag::err_static_main : diag::warn_static_main)
@@ -6245,6 +6915,14 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
if (FD->isInlineSpecified())
Diag(DS.getInlineSpecLoc(), diag::err_inline_main)
<< FixItHint::CreateRemoval(DS.getInlineSpecLoc());
+ if (DS.isNoreturnSpecified()) {
+ SourceLocation NoreturnLoc = DS.getNoreturnSpecLoc();
+ SourceRange NoreturnRange(NoreturnLoc,
+ PP.getLocForEndOfToken(NoreturnLoc));
+ Diag(NoreturnLoc, diag::ext_noreturn_main);
+ Diag(NoreturnLoc, diag::note_main_remove_noreturn)
+ << FixItHint::CreateRemoval(NoreturnRange);
+ }
if (FD->isConstexpr()) {
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main)
<< FixItHint::CreateRemoval(DS.getConstexprSpecLoc());
@@ -6268,9 +6946,20 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
} else if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) {
Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint);
+ SourceRange ResultRange = getResultSourceRange(FD);
+ if (ResultRange.isValid())
+ Diag(ResultRange.getBegin(), diag::note_main_change_return_type)
+ << FixItHint::CreateReplacement(ResultRange, "int");
+
// Otherwise, this is just a flat-out error.
} else {
- Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+ SourceRange ResultRange = getResultSourceRange(FD);
+ if (ResultRange.isValid())
+ Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint)
+ << FixItHint::CreateReplacement(ResultRange, "int");
+ else
+ Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+
FD->setInvalidDecl(true);
}
@@ -6319,7 +7008,8 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
const PointerType* PT;
if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
(PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
- (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) {
+ Context.hasSameType(QualType(qs.strip(PT->getPointeeType()), 0),
+ Context.CharTy)) {
qs.removeConst();
mismatch = !qs.empty();
}
@@ -6457,6 +7147,14 @@ namespace {
Visit(Base);
}
+ void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ if (E->getNumArgs() > 0)
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getArg(0)))
+ HandleDeclRefExpr(DRE);
+
+ Inherited::VisitCXXOperatorCallExpr(E);
+ }
+
void VisitUnaryOperator(UnaryOperator *E) {
// For POD record types, addresses of its own members are well-defined.
if (E->getOpcode() == UO_AddrOf && isRecordType &&
@@ -6471,11 +7169,17 @@ namespace {
void VisitObjCMessageExpr(ObjCMessageExpr *E) { return; }
void HandleDeclRefExpr(DeclRefExpr *DRE) {
- Decl* ReferenceDecl = DRE->getDecl();
+ Decl* ReferenceDecl = DRE->getDecl();
if (OrigDecl != ReferenceDecl) return;
- unsigned diag = isReferenceType
- ? diag::warn_uninit_self_reference_in_reference_init
- : diag::warn_uninit_self_reference_in_init;
+ unsigned diag;
+ if (isReferenceType) {
+ diag = diag::warn_uninit_self_reference_in_reference_init;
+ } else if (cast<VarDecl>(OrigDecl)->isStaticLocal()) {
+ diag = diag::warn_static_self_reference_in_init;
+ } else {
+ diag = diag::warn_uninit_self_reference_in_init;
+ }
+
S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
S.PDiag(diag)
<< DRE->getNameInfo().getName()
@@ -6572,6 +7276,20 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
DeduceInit = CXXDirectInit->getExpr(0);
}
}
+
+ // 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.take();
+ DefaultedToAuto = true;
+ }
+
TypeSourceInfo *DeducedType = 0;
if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
DAR_Failed)
@@ -6582,8 +7300,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
VDecl->setTypeSourceInfo(DeducedType);
VDecl->setType(DeducedType->getType());
- VDecl->ClearLinkageCache();
-
+ assert(VDecl->isLinkageValid());
+
// In ARC, infer lifetime.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
VDecl->setInvalidDecl();
@@ -6592,7 +7310,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// '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() &&
+ if (ActiveTemplateInstantiations.empty() && !DefaultedToAuto &&
DeducedType->getType()->isObjCIdType()) {
SourceLocation Loc = DeducedType->getTypeLoc().getBeginLoc();
Diag(Loc, diag::warn_auto_var_is_id)
@@ -6602,7 +7320,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
if (VarDecl *Old = VDecl->getPreviousDecl())
- MergeVarDeclTypes(VDecl, Old);
+ MergeVarDeclTypes(VDecl, Old, /*OldWasHidden*/ false);
}
if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) {
@@ -6683,17 +7401,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// CheckInitializerTypes may change it.
QualType DclT = VDecl->getType(), SavT = DclT;
- // Top-level message sends default to 'id' when we're in a debugger
- // and we are assigning it to a variable of 'id' type.
- if (getLangOpts().DebuggerCastResultToId && DclT->isObjCIdType())
- if (Init->getType() == Context.UnknownAnyTy && isa<ObjCMessageExpr>(Init)) {
- ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
- if (Result.isInvalid()) {
- VDecl->setInvalidDecl();
- return;
- }
- Init = Result.take();
+ // Expressions default to 'id' when we're in a debugger
+ // and we are assigning it to a variable of Objective-C pointer type.
+ if (getLangOpts().DebuggerCastResultToId && DclT->isObjCObjectPointerType() &&
+ Init->getType() == Context.UnknownAnyTy) {
+ ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
}
+ Init = Result.take();
+ }
// Perform the initialization.
if (!VDecl->isInvalidDecl()) {
@@ -6740,9 +7458,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (!VDecl->isInvalidDecl() && (DclT != SavT))
VDecl->setType(DclT);
- // Check any implicit conversions within the expression.
- CheckImplicitConversions(Init, VDecl->getLocation());
-
if (!VDecl->isInvalidDecl()) {
checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init);
@@ -6765,7 +7480,26 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
}
- Init = MaybeCreateExprWithCleanups(Init);
+ // The initialization is usually a full-expression.
+ //
+ // FIXME: If this is a braced initialization of an aggregate, it is not
+ // an expression, and each individual field initializer is a separate
+ // full-expression. For instance, in:
+ //
+ // struct Temp { ~Temp(); };
+ // struct S { S(Temp); };
+ // struct T { S a, b; } t = { Temp(), Temp() }
+ //
+ // we should destroy the first Temp before constructing the second.
+ ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(),
+ false,
+ VDecl->isConstexpr());
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+ Init = Result.take();
+
// Attach the initializer to the decl.
VDecl->setInit(Init);
@@ -6817,7 +7551,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
} else if (DclT->isIntegralOrEnumerationType()) {
// Check whether the expression is a constant expression.
SourceLocation Loc;
- if (getLangOpts().CPlusPlus0x && DclT.isVolatileQualified())
+ if (getLangOpts().CPlusPlus11 && DclT.isVolatileQualified())
// In C++11, a non-constexpr const static data member with an
// in-class initializer cannot be volatile.
Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile);
@@ -6840,21 +7574,28 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// We allow foldable floating-point constants as an extension.
} else if (DclT->isFloatingType()) { // also permits complex, which is ok
- Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
- << DclT << Init->getSourceRange();
- if (getLangOpts().CPlusPlus0x)
+ // In C++98, this is a GNU extension. In C++11, it is not, but we support
+ // it anyway and provide a fixit to add the 'constexpr'.
+ if (getLangOpts().CPlusPlus11) {
Diag(VDecl->getLocation(),
- diag::note_in_class_initializer_float_type_constexpr)
- << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
+ diag::ext_in_class_initializer_float_type_cxx11)
+ << DclT << Init->getSourceRange();
+ Diag(VDecl->getLocStart(),
+ diag::note_in_class_initializer_float_type_cxx11)
+ << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
+ } else {
+ Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
+ << DclT << Init->getSourceRange();
- if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) {
- Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
- << Init->getSourceRange();
- VDecl->setInvalidDecl();
+ if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) {
+ Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
+ << Init->getSourceRange();
+ VDecl->setInvalidDecl();
+ }
}
// Suggest adding 'constexpr' in C++11 for literal types.
- } else if (getLangOpts().CPlusPlus0x && DclT->isLiteralType()) {
+ } else if (getLangOpts().CPlusPlus11 && DclT->isLiteralType()) {
Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type)
<< DclT << Init->getSourceRange()
<< FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
@@ -6866,9 +7607,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
}
} else if (VDecl->isFileVarDecl()) {
- if (VDecl->getStorageClassAsWritten() == SC_Extern &&
+ if (VDecl->getStorageClass() == SC_Extern &&
(!getLangOpts().CPlusPlus ||
- !Context.getBaseElementType(VDecl->getType()).isConstQualified()))
+ !(Context.getBaseElementType(VDecl->getType()).isConstQualified() ||
+ VDecl->isExternC())))
Diag(VDecl->getLocation(), diag::warn_extern_init);
// C99 6.7.8p4. All file scoped initializers need to be constant.
@@ -7155,7 +7897,7 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
// for-range-declaration cannot be given a storage class specifier.
int Error = -1;
- switch (VD->getStorageClassAsWritten()) {
+ switch (VD->getStorageClass()) {
case SC_None:
break;
case SC_Extern:
@@ -7206,7 +7948,10 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
if (var->isThisDeclarationADefinition() &&
- var->getLinkage() == ExternalLinkage) {
+ var->hasExternalLinkage() &&
+ getDiagnostics().getDiagnosticLevel(
+ diag::warn_missing_variable_declarations,
+ var->getLocation())) {
// Find a previous declaration that's not a definition.
VarDecl *prev = var->getPreviousDecl();
while (prev && prev->isThisDeclarationADefinition())
@@ -7230,12 +7975,13 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
// Regardless, we don't want to ignore array nesting when
// constructing this copy.
if (type->isStructureOrClassType()) {
+ EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
SourceLocation poi = var->getLocation();
Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi);
- ExprResult result =
- PerformCopyInitialization(
- InitializedEntity::InitializeBlock(poi, type, false),
- poi, Owned(varRef));
+ ExprResult result
+ = PerformMoveOrCopyInitialization(
+ InitializedEntity::InitializeBlock(poi, type, false),
+ var, var->getType(), varRef, /*AllowNRVO=*/true);
if (!result.isInvalid()) {
result = MaybeCreateExprWithCleanups(result);
Expr *init = result.takeAs<Expr>();
@@ -7259,7 +8005,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
<< Init->getSourceRange();
if (var->isConstexpr()) {
- llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ SmallVector<PartialDiagnosticAt, 8> Notes;
if (!var->evaluateValue(Notes) || !var->isInitICE()) {
SourceLocation DiagLoc = var->getLocation();
// If the note doesn't add any useful information other than a source
@@ -7294,40 +8040,52 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
// Note that we are no longer parsing the initializer for this declaration.
ParsingInitForAutoVars.erase(ThisDecl);
+ VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDecl);
+ if (!VD)
+ return;
+
+ const DeclContext *DC = VD->getDeclContext();
+ // If there's a #pragma GCC visibility in scope, and this isn't a class
+ // member, set the visibility of this variable.
+ if (!DC->isRecord() && VD->hasExternalLinkage())
+ AddPushedVisibilityAttribute(VD);
+
+ if (VD->isFileVarDecl())
+ MarkUnusedFileScopedDecl(VD);
+
// Now we have parsed the initializer and can update the table of magic
// tag values.
- if (ThisDecl && ThisDecl->hasAttr<TypeTagForDatatypeAttr>()) {
- const VarDecl *VD = dyn_cast<VarDecl>(ThisDecl);
- if (VD && VD->getType()->isIntegralOrEnumerationType()) {
- for (specific_attr_iterator<TypeTagForDatatypeAttr>
- I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(),
- E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>();
- I != E; ++I) {
- const Expr *MagicValueExpr = VD->getInit();
- if (!MagicValueExpr) {
- continue;
- }
- llvm::APSInt MagicValueInt;
- if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) {
- Diag(I->getRange().getBegin(),
- diag::err_type_tag_for_datatype_not_ice)
- << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
- continue;
- }
- if (MagicValueInt.getActiveBits() > 64) {
- Diag(I->getRange().getBegin(),
- diag::err_type_tag_for_datatype_too_large)
- << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
- continue;
- }
- uint64_t MagicValue = MagicValueInt.getZExtValue();
- RegisterTypeTagForDatatype(I->getArgumentKind(),
- MagicValue,
- I->getMatchingCType(),
- I->getLayoutCompatible(),
- I->getMustBeNull());
- }
+ if (!VD->hasAttr<TypeTagForDatatypeAttr>() ||
+ !VD->getType()->isIntegralOrEnumerationType())
+ return;
+
+ for (specific_attr_iterator<TypeTagForDatatypeAttr>
+ I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(),
+ E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>();
+ I != E; ++I) {
+ const Expr *MagicValueExpr = VD->getInit();
+ if (!MagicValueExpr) {
+ continue;
+ }
+ llvm::APSInt MagicValueInt;
+ if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) {
+ Diag(I->getRange().getBegin(),
+ diag::err_type_tag_for_datatype_not_ice)
+ << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
+ continue;
+ }
+ if (MagicValueInt.getActiveBits() > 64) {
+ Diag(I->getRange().getBegin(),
+ diag::err_type_tag_for_datatype_too_large)
+ << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
+ continue;
}
+ uint64_t MagicValue = MagicValueInt.getZExtValue();
+ RegisterTypeTagForDatatype(I->getArgumentKind(),
+ MagicValue,
+ I->getMatchingCType(),
+ I->getLayoutCompatible(),
+ I->getMustBeNull());
}
}
@@ -7343,6 +8101,10 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (Decl *D = Group[i])
Decls.push_back(D);
+ if (DeclSpec::isDeclRep(DS.getTypeSpecType()))
+ if (const TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl()))
+ getASTContext().addUnnamedTag(Tag);
+
return BuildDeclaratorGroup(Decls.data(), Decls.size(),
DS.getTypeSpecType() == DeclSpec::TST_auto);
}
@@ -7449,14 +8211,11 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
// C++03 [dcl.stc]p2 also permits 'auto'.
VarDecl::StorageClass StorageClass = SC_None;
- VarDecl::StorageClass StorageClassAsWritten = SC_None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
StorageClass = SC_Register;
- StorageClassAsWritten = SC_Register;
} else if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
StorageClass = SC_Auto;
- StorageClassAsWritten = SC_Auto;
} else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
Diag(DS.getStorageClassSpecLoc(),
diag::err_invalid_storage_class_in_func_decl);
@@ -7469,7 +8228,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 0;
- DiagnoseFunctionSpecifiers(D);
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType parmDeclType = TInfo->getType();
@@ -7529,7 +8288,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
D.getLocStart(),
D.getIdentifierLoc(), II,
parmDeclType, TInfo,
- StorageClass, StorageClassAsWritten);
+ StorageClass);
if (D.isInvalidType())
New->setInvalidDecl();
@@ -7568,7 +8327,7 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
location for the unnamed parameters, embedding the parameter's type? */
ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0,
T, Context.getTrivialTypeSourceInfo(T, Loc),
- SC_None, SC_None, 0);
+ SC_None, 0);
Param->setImplicit();
return Param;
}
@@ -7621,8 +8380,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param,
ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
SourceLocation NameLoc, IdentifierInfo *Name,
QualType T, TypeSourceInfo *TSInfo,
- VarDecl::StorageClass StorageClass,
- VarDecl::StorageClass StorageClassAsWritten) {
+ VarDecl::StorageClass StorageClass) {
// In ARC, infer a lifetime qualifier for appropriate parameter types.
if (getLangOpts().ObjCAutoRefCount &&
T.getObjCLifetime() == Qualifiers::OCL_None &&
@@ -7649,8 +8407,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
Context.getAdjustedParameterType(T),
TSInfo,
- StorageClass, StorageClassAsWritten,
- 0);
+ StorageClass, 0);
// Parameters can not be abstract class types.
// For record types, this is done by the AbstractClassUsageDiagnoser once
@@ -7730,7 +8487,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
-static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
+static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
+ const FunctionDecl*& PossibleZeroParamPrototype) {
// Don't warn about invalid declarations.
if (FD->isInvalidDecl())
return false;
@@ -7772,6 +8530,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
continue;
MissingPrototype = !Prev->getType()->isFunctionProtoType();
+ if (FD->getNumParams() == 0)
+ PossibleZeroParamPrototype = Prev;
break;
}
@@ -7837,8 +8597,22 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// prototype declaration. This warning is issued even if the
// definition itself provides a prototype. The aim is to detect
// global functions that fail to be declared in header files.
- if (ShouldWarnAboutMissingPrototype(FD))
+ const FunctionDecl *PossibleZeroParamPrototype = 0;
+ if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+
+ if (PossibleZeroParamPrototype) {
+ // We found a declaration that is not a prototype,
+ // but that could be a zero-parameter prototype
+ TypeSourceInfo* TI = PossibleZeroParamPrototype->getTypeSourceInfo();
+ TypeLoc TL = TI->getTypeLoc();
+ if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
+ Diag(PossibleZeroParamPrototype->getLocation(),
+ diag::note_declaration_not_a_prototype)
+ << PossibleZeroParamPrototype
+ << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
+ }
+ }
if (FnBodyScope)
PushDeclContext(FnBodyScope, FD);
@@ -7913,7 +8687,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
<< "dllimport";
FD->setInvalidDecl();
- return FD;
+ return D;
}
// Visual C++ appears to not think this is an issue, so only issue
@@ -7930,7 +8704,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// We want to attach documentation to original Decl (which might be
// a function template).
ActOnDocumentableDecl(D);
- return FD;
+ return D;
}
/// \brief Given the set of return statements within a function body,
@@ -7967,6 +8741,33 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
}
+bool Sema::canSkipFunctionBody(Decl *D) {
+ if (!Consumer.shouldSkipFunctionBody(D))
+ return false;
+
+ if (isa<ObjCMethodDecl>(D))
+ return true;
+
+ FunctionDecl *FD = 0;
+ if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ FD = FTD->getTemplatedDecl();
+ else
+ FD = cast<FunctionDecl>(D);
+
+ // We cannot skip the body of a function (or function template) which is
+ // constexpr, since we may need to evaluate its body in order to parse the
+ // rest of the file.
+ return !FD->isConstexpr();
+}
+
+Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
+ if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Decl))
+ FD->setHasSkippedBody();
+ else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Decl))
+ MD->setHasSkippedBody();
+ return ActOnFinishFunctionBody(Decl, 0);
+}
+
Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
return ActOnFinishFunctionBody(D, BodyArg, false);
}
@@ -7986,6 +8787,18 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD) {
FD->setBody(Body);
+ // The only way to be included in UndefinedButUsed is if there is an
+ // ODR use before the definition. Avoid the expensive map lookup if this
+ // is the first declaration.
+ if (FD->getPreviousDecl() != 0 && FD->getPreviousDecl()->isUsed()) {
+ if (FD->getLinkage() != ExternalLinkage)
+ UndefinedButUsed.erase(FD);
+ else if (FD->isInlined() &&
+ (LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
+ (!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>()))
+ UndefinedButUsed.erase(FD);
+ }
+
// If the function implicitly returns zero (like 'main') or is naked,
// don't complain about missing return statements.
if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())
@@ -8068,7 +8881,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (PP.getDiagnostics().hasErrorOccurred() ||
PP.getDiagnostics().getSuppressAllDiagnostics()) {
DiscardCleanupsInEvaluationContext();
- } else if (!isa<FunctionTemplateDecl>(dcl)) {
+ }
+ if (!PP.getDiagnostics().hasUncompilableErrorOccurred() &&
+ !isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
// enabled.
ActivePolicy = &WP;
@@ -8125,8 +8940,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
// this name as a function or variable. If so, use that
// (non-visible) declaration, and complain about it.
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternalDecl(&II);
- if (Pos != LocallyScopedExternalDecls.end()) {
+ = findLocallyScopedExternCDecl(&II);
+ if (Pos != LocallyScopedExternCDecls.end()) {
Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second;
Diag(Pos->second->getLocation(), diag::note_previous_declaration);
return Pos->second;
@@ -8202,7 +9017,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
DeclContext *PrevDC = CurContext;
CurContext = Context.getTranslationUnitDecl();
- FunctionDecl *FD = dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
+ FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
FD->setImplicit();
CurContext = PrevDC;
@@ -8376,9 +9191,13 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
QualType T = TI->getType();
- if (T->isDependentType() || T->isIntegralType(Context))
+ if (T->isDependentType())
return false;
+ if (const BuiltinType *BT = T->getAs<BuiltinType>())
+ if (BT->isInteger())
+ return false;
+
Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T;
return true;
}
@@ -8575,6 +9394,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
TUK == TUK_Friend,
isExplicitSpecialization,
Invalid)) {
+ if (Kind == TTK_Enum) {
+ Diag(KWLoc, diag::err_enum_template);
+ return 0;
+ }
+
if (TemplateParams->size() > 0) {
// This is a declaration or definition of a class template (which may
// be a member of another template).
@@ -8703,6 +9527,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// shouldn't be diagnosing.
LookupName(Previous, S);
+ // When declaring or defining a tag, ignore ambiguities introduced
+ // by types using'ed into this scope.
if (Previous.isAmbiguous() &&
(TUK == TUK_Definition || TUK == TUK_Declaration)) {
LookupResult::Filter F = Previous.makeFilter();
@@ -8713,6 +9539,27 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
F.done();
}
+
+ // C++11 [namespace.memdef]p3:
+ // If the name in a friend declaration is neither qualified nor
+ // a template-id and the declaration is a function or an
+ // elaborated-type-specifier, the lookup to determine whether
+ // the entity has been previously declared shall not consider
+ // any scopes outside the innermost enclosing namespace.
+ //
+ // Does it matter that this should be by scope instead of by
+ // semantic context?
+ if (!Previous.empty() && TUK == TUK_Friend) {
+ DeclContext *EnclosingNS = SearchDC->getEnclosingNamespaceContext();
+ LookupResult::Filter F = Previous.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *ND = F.next();
+ DeclContext *DC = ND->getDeclContext()->getRedeclContext();
+ if (DC->isFileContext() && !EnclosingNS->Encloses(ND->getDeclContext()))
+ F.erase();
+ }
+ F.done();
+ }
// Note: there used to be some attempt at recovery here.
if (Previous.isAmbiguous())
@@ -9070,7 +9917,8 @@ CreateNewDecl:
// If this is an undefined enum, warn.
if (TUK != TUK_Definition && !Invalid) {
TagDecl *Def;
- if (getLangOpts().CPlusPlus0x && cast<EnumDecl>(New)->isFixed()) {
+ if ((getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) &&
+ cast<EnumDecl>(New)->isFixed()) {
// C++0x: 7.2p2: opaque-enum-declaration.
// Conflicts are diagnosed above. Do nothing.
}
@@ -9250,7 +10098,9 @@ CreateNewDecl:
AddPushedVisibilityAttribute(New);
OwnedDecl = true;
- return New;
+ // In C++, don't return an invalid declaration. We can't recover well from
+ // the cases where we make the type anonymous.
+ return (Invalid && getLangOpts().CPlusPlus) ? 0 : New;
}
void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
@@ -9330,7 +10180,11 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
// Exit this scope of this tag's definition.
PopDeclContext();
-
+
+ if (getCurLexicalContext()->isObjCContainer() &&
+ Tag->getDeclContext()->isFileContext())
+ Tag->setTopLevelDeclInObjCContainer();
+
// Notify the consumer that we've defined a tag.
Consumer.HandleTagDeclDefinition(Tag);
}
@@ -9479,14 +10333,24 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
}
}
- DiagnoseFunctionSpecifiers(D);
+ // TR 18037 does not allow fields to be declared with address spaces.
+ if (T.getQualifiers().hasAddressSpace()) {
+ Diag(Loc, diag::err_field_with_address_space);
+ D.setInvalidType();
+ }
+
+ // OpenCL 1.2 spec, s6.9 r:
+ // The event type cannot be used to declare a structure or union field.
+ if (LangOpts.OpenCL && T->isEventT()) {
+ Diag(Loc, diag::err_event_t_struct_field);
+ D.setInvalidType();
+ }
+
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
- if (D.getDeclSpec().isConstexprSpecified())
- Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
- << 2;
-
+
// Check to see if this name was declared as a member previously
NamedDecl *PrevDecl = 0;
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
@@ -9587,6 +10451,12 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
}
}
+ // OpenCL v1.2 s6.9.c: bitfields are not supported.
+ if (BitWidth && getLangOpts().OpenCL) {
+ Diag(Loc, diag::err_opencl_bitfields);
+ InvalidDecl = true;
+ }
+
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
@@ -9686,10 +10556,14 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// FIXME: We need to pass in the attributes given an AST
// representation, not a parser representation.
- if (D)
+ if (D) {
// FIXME: What to pass instead of TUScope?
ProcessDeclAttributes(TUScope, NewFD, *D);
+ if (NewFD->hasAttrs())
+ CheckAlignasUnderalignment(NewFD);
+ }
+
// In auto-retain/release, infer strong retension for fields of
// retainable type.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD))
@@ -9711,24 +10585,29 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
QualType EltTy = Context.getBaseElementType(FD->getType());
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
- CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+ CXXRecordDecl *RDecl = cast<CXXRecordDecl>(RT->getDecl());
if (RDecl->getDefinition()) {
// We check for copy constructors before constructors
// because otherwise we'll never get complaints about
// copy constructors.
CXXSpecialMember member = CXXInvalid;
- if (!RDecl->hasTrivialCopyConstructor())
+ // We're required to check for any non-trivial constructors. Since the
+ // implicit default constructor is suppressed if there are any
+ // user-declared constructors, we just need to check that there is a
+ // trivial default constructor and a trivial copy constructor. (We don't
+ // worry about move constructors here, since this is a C++98 check.)
+ if (RDecl->hasNonTrivialCopyConstructor())
member = CXXCopyConstructor;
else if (!RDecl->hasTrivialDefaultConstructor())
member = CXXDefaultConstructor;
- else if (!RDecl->hasTrivialCopyAssignment())
+ else if (RDecl->hasNonTrivialCopyAssignment())
member = CXXCopyAssignment;
- else if (!RDecl->hasTrivialDestructor())
+ else if (RDecl->hasNonTrivialDestructor())
member = CXXDestructor;
if (member != CXXInvalid) {
- if (!getLangOpts().CPlusPlus0x &&
+ if (!getLangOpts().CPlusPlus11 &&
getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) {
// Objective-C++ ARC: it is an error to have a non-trivial field of
// a union. However, system headers in Objective-C programs
@@ -9744,192 +10623,17 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
}
}
- Diag(FD->getLocation(), getLangOpts().CPlusPlus0x ?
+ 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;
- DiagnoseNontrivial(RT, member);
- return !getLangOpts().CPlusPlus0x;
- }
- }
- }
-
- return false;
-}
-
-/// If the given constructor is user-declared, produce a diagnostic explaining
-/// that it makes the class non-trivial.
-static bool diagnoseNonTrivialUserDeclaredCtor(Sema &S, QualType QT,
- CXXConstructorDecl *CD,
- Sema::CXXSpecialMember CSM) {
- if (CD->isImplicit())
- return false;
-
- SourceLocation CtorLoc = CD->getLocation();
- S.Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << CSM;
- return true;
-}
-
-/// DiagnoseNontrivial - Given that a class has a non-trivial
-/// special member, figure out why.
-void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
- QualType QT(T, 0U);
- CXXRecordDecl* RD = cast<CXXRecordDecl>(T->getDecl());
-
- // Check whether the member was user-declared.
- switch (member) {
- case CXXInvalid:
- break;
-
- case CXXDefaultConstructor:
- if (RD->hasUserDeclaredConstructor()) {
- typedef CXXRecordDecl::ctor_iterator ctor_iter;
- for (ctor_iter CI = RD->ctor_begin(), CE = RD->ctor_end(); CI != CE; ++CI)
- if (diagnoseNonTrivialUserDeclaredCtor(*this, QT, *CI, member))
- return;
-
- // No user-delcared constructors; look for constructor templates.
- typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl>
- tmpl_iter;
- for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end());
- TI != TE; ++TI) {
- CXXConstructorDecl *CD =
- dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl());
- if (CD && diagnoseNonTrivialUserDeclaredCtor(*this, QT, CD, member))
- return;
- }
- }
- break;
-
- case CXXCopyConstructor:
- if (RD->hasUserDeclaredCopyConstructor()) {
- SourceLocation CtorLoc =
- RD->getCopyConstructor(0)->getLocation();
- Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
-
- case CXXMoveConstructor:
- if (RD->hasUserDeclaredMoveConstructor()) {
- SourceLocation CtorLoc = RD->getMoveConstructor()->getLocation();
- Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
-
- case CXXCopyAssignment:
- if (RD->hasUserDeclaredCopyAssignment()) {
- SourceLocation AssignLoc =
- RD->getCopyAssignmentOperator(0)->getLocation();
- Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
-
- case CXXMoveAssignment:
- if (RD->hasUserDeclaredMoveAssignment()) {
- SourceLocation AssignLoc = RD->getMoveAssignmentOperator()->getLocation();
- Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
-
- case CXXDestructor:
- if (RD->hasUserDeclaredDestructor()) {
- SourceLocation DtorLoc = LookupDestructor(RD)->getLocation();
- Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
- }
-
- typedef CXXRecordDecl::base_class_iterator base_iter;
-
- // Virtual bases and members inhibit trivial copying/construction,
- // but not trivial destruction.
- if (member != CXXDestructor) {
- // Check for virtual bases. vbases includes indirect virtual bases,
- // so we just iterate through the direct bases.
- for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi)
- if (bi->isVirtual()) {
- SourceLocation BaseLoc = bi->getLocStart();
- Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1;
- return;
- }
-
- // Check for virtual methods.
- typedef CXXRecordDecl::method_iterator meth_iter;
- for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
- ++mi) {
- if (mi->isVirtual()) {
- SourceLocation MLoc = mi->getLocStart();
- Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0;
- return;
- }
- }
- }
-
- bool (CXXRecordDecl::*hasTrivial)() const;
- switch (member) {
- case CXXDefaultConstructor:
- hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break;
- case CXXCopyConstructor:
- hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;
- case CXXCopyAssignment:
- hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break;
- case CXXDestructor:
- hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break;
- default:
- llvm_unreachable("unexpected special member");
- }
-
- // Check for nontrivial bases (and recurse).
- for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) {
- const RecordType *BaseRT = bi->getType()->getAs<RecordType>();
- assert(BaseRT && "Don't know how to handle dependent bases");
- CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl());
- if (!(BaseRecTy->*hasTrivial)()) {
- SourceLocation BaseLoc = bi->getLocStart();
- Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member;
- DiagnoseNontrivial(BaseRT, member);
- return;
- }
- }
-
- // Check for nontrivial members (and recurse).
- typedef RecordDecl::field_iterator field_iter;
- for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe;
- ++fi) {
- QualType EltTy = Context.getBaseElementType(fi->getType());
- if (const RecordType *EltRT = EltTy->getAs<RecordType>()) {
- CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl());
-
- if (!(EltRD->*hasTrivial)()) {
- SourceLocation FLoc = fi->getLocation();
- Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member;
- DiagnoseNontrivial(EltRT, member);
- return;
- }
- }
-
- if (EltTy->isObjCLifetimeType()) {
- switch (EltTy.getObjCLifetime()) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- break;
-
- case Qualifiers::OCL_Autoreleasing:
- case Qualifiers::OCL_Weak:
- case Qualifiers::OCL_Strong:
- Diag(fi->getLocation(), diag::note_nontrivial_objc_ownership)
- << QT << EltTy.getObjCLifetime();
- return;
+ DiagnoseNontrivial(RDecl, member);
+ return !getLangOpts().CPlusPlus11;
}
}
}
- llvm_unreachable("found no explanation for non-trivial member");
+ return false;
}
/// TranslateIvarVisibility - Translate visibility from a token ID to an
@@ -10058,8 +10762,8 @@ Decl *Sema::ActOnIvar(Scope *S,
}
/// ActOnLastBitfield - This routine handles synthesized bitfields rules for
-/// class and class extensions. For every class @interface and class
-/// extension @interface, if the last ivar is a bitfield of any type,
+/// class and class extensions. For every class \@interface and class
+/// extension \@interface, if the last ivar is a bitfield of any type,
/// then add an implicit `char :0` ivar to the end of that interface.
void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
SmallVectorImpl<Decl *> &AllIvarDecls) {
@@ -10259,52 +10963,54 @@ void Sema::ActOnFields(Scope* S,
}
if (Record && FDTTy->getDecl()->hasObjectMember())
Record->setHasObjectMember(true);
+ if (Record && FDTTy->getDecl()->hasVolatileMember())
+ Record->setHasVolatileMember(true);
} else if (FDTy->isObjCObjectType()) {
/// A field cannot be an Objective-c object
Diag(FD->getLocation(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(FD->getLocation(), "*");
QualType T = Context.getObjCObjectPointerType(FD->getType());
FD->setType(T);
- } else if (!getLangOpts().CPlusPlus) {
- if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported) {
- // It's an error in ARC if a field has lifetime.
- // We don't want to report this in a system header, though,
- // so we just make the field unavailable.
- // FIXME: that's really not sufficient; we need to make the type
- // itself invalid to, say, initialize or copy.
- QualType T = FD->getType();
- Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime();
- if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) {
- SourceLocation loc = FD->getLocation();
- if (getSourceManager().isInSystemHeader(loc)) {
- if (!FD->hasAttr<UnavailableAttr>()) {
- FD->addAttr(new (Context) UnavailableAttr(loc, Context,
- "this system field has retaining ownership"));
- }
- } else {
- Diag(FD->getLocation(), diag::err_arc_objc_object_in_struct)
- << T->isBlockPointerType();
+ } else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported &&
+ (!getLangOpts().CPlusPlus || Record->isUnion())) {
+ // It's an error in ARC if a field has lifetime.
+ // We don't want to report this in a system header, though,
+ // so we just make the field unavailable.
+ // FIXME: that's really not sufficient; we need to make the type
+ // itself invalid to, say, initialize or copy.
+ QualType T = FD->getType();
+ Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime();
+ if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) {
+ SourceLocation loc = FD->getLocation();
+ if (getSourceManager().isInSystemHeader(loc)) {
+ if (!FD->hasAttr<UnavailableAttr>()) {
+ FD->addAttr(new (Context) UnavailableAttr(loc, Context,
+ "this system field has retaining ownership"));
}
- ARCErrReported = true;
+ } else {
+ Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
+ << T->isBlockPointerType() << Record->getTagKind();
}
+ ARCErrReported = true;
}
- else if (getLangOpts().ObjC1 &&
+ } else if (getLangOpts().ObjC1 &&
getLangOpts().getGC() != LangOptions::NonGC &&
Record && !Record->hasObjectMember()) {
- if (FD->getType()->isObjCObjectPointerType() ||
- FD->getType().isObjCGCStrong())
+ if (FD->getType()->isObjCObjectPointerType() ||
+ FD->getType().isObjCGCStrong())
+ Record->setHasObjectMember(true);
+ else if (Context.getAsArrayType(FD->getType())) {
+ QualType BaseType = Context.getBaseElementType(FD->getType());
+ if (BaseType->isRecordType() &&
+ BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
Record->setHasObjectMember(true);
- else if (Context.getAsArrayType(FD->getType())) {
- QualType BaseType = Context.getBaseElementType(FD->getType());
- if (BaseType->isRecordType() &&
- BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
- Record->setHasObjectMember(true);
- else if (BaseType->isObjCObjectPointerType() ||
- BaseType.isObjCGCStrong())
- Record->setHasObjectMember(true);
- }
+ else if (BaseType->isObjCObjectPointerType() ||
+ BaseType.isObjCGCStrong())
+ Record->setHasObjectMember(true);
}
}
+ if (Record && FD->getType().isVolatileQualified())
+ Record->setHasVolatileMember(true);
// Keep track of the number of named members.
if (FD->getIdentifier())
++NumNamedMembers;
@@ -10316,14 +11022,14 @@ void Sema::ActOnFields(Scope* S,
if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
if (!CXXRecord->isInvalidDecl()) {
// Set access bits correctly on the directly-declared conversions.
- UnresolvedSetImpl *Convs = CXXRecord->getConversionFunctions();
- for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end();
- I != E; ++I)
- Convs->setAccess(I, (*I)->getAccess());
+ for (CXXRecordDecl::conversion_iterator
+ I = CXXRecord->conversion_begin(),
+ E = CXXRecord->conversion_end(); I != E; ++I)
+ I.setAccess((*I)->getAccess());
if (!CXXRecord->isDependentType()) {
// Adjust user-defined destructor exception spec.
- if (getLangOpts().CPlusPlus0x &&
+ if (getLangOpts().CPlusPlus11 &&
CXXRecord->hasUserDeclaredDestructor())
AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor());
@@ -10376,6 +11082,8 @@ void Sema::ActOnFields(Scope* S,
if (!Completed)
Record->completeDefinition();
+ if (Record->hasAttrs())
+ CheckAlignasUnderalignment(Record);
} else {
ObjCIvarDecl **ClsFields =
reinterpret_cast<ObjCIvarDecl**>(RecFields.data());
@@ -10418,11 +11126,12 @@ void Sema::ActOnFields(Scope* S,
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
continue;
}
- for (const ObjCCategoryDecl *ClsExtDecl =
- IDecl->getFirstClassExtension();
- ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
- if (const ObjCIvarDecl *ClsExtIvar =
- ClsExtDecl->getIvarDecl(ClsFields[i]->getIdentifier())) {
+ for (ObjCInterfaceDecl::known_extensions_iterator
+ Ext = IDecl->known_extensions_begin(),
+ ExtEnd = IDecl->known_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ if (const ObjCIvarDecl *ClsExtIvar
+ = Ext->getIvarDecl(ClsFields[i]->getIdentifier())) {
Diag(ClsFields[i]->getLocation(),
diag::err_duplicate_ivar_declaration);
Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);
@@ -10503,7 +11212,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
EltTy = Context.DependentTy;
else {
SourceLocation ExpLoc;
- if (getLangOpts().CPlusPlus0x && Enum->isFixed() &&
+ if (getLangOpts().CPlusPlus11 && Enum->isFixed() &&
!getLangOpts().MicrosoftMode) {
// C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
// constant-expression in the enumerator-definition shall be a converted
@@ -10722,6 +11431,182 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
return New;
}
+// Returns true when the enum initial expression does not trigger the
+// duplicate enum warning. A few common cases are exempted as follows:
+// Element2 = Element1
+// Element2 = Element1 + 1
+// Element2 = Element1 - 1
+// Where Element2 and Element1 are from the same enum.
+static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) {
+ Expr *InitExpr = ECD->getInitExpr();
+ if (!InitExpr)
+ return true;
+ InitExpr = InitExpr->IgnoreImpCasts();
+
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr)) {
+ if (!BO->isAdditiveOp())
+ return true;
+ IntegerLiteral *IL = dyn_cast<IntegerLiteral>(BO->getRHS());
+ if (!IL)
+ return true;
+ if (IL->getValue() != 1)
+ return true;
+
+ InitExpr = BO->getLHS();
+ }
+
+ // This checks if the elements are from the same enum.
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InitExpr);
+ if (!DRE)
+ return true;
+
+ EnumConstantDecl *EnumConstant = dyn_cast<EnumConstantDecl>(DRE->getDecl());
+ if (!EnumConstant)
+ return true;
+
+ if (cast<EnumDecl>(TagDecl::castFromDeclContext(ECD->getDeclContext())) !=
+ Enum)
+ return true;
+
+ return false;
+}
+
+struct DupKey {
+ int64_t val;
+ bool isTombstoneOrEmptyKey;
+ DupKey(int64_t val, bool isTombstoneOrEmptyKey)
+ : val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {}
+};
+
+static DupKey GetDupKey(const llvm::APSInt& Val) {
+ return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(),
+ false);
+}
+
+struct DenseMapInfoDupKey {
+ static DupKey getEmptyKey() { return DupKey(0, true); }
+ static DupKey getTombstoneKey() { return DupKey(1, true); }
+ static unsigned getHashValue(const DupKey Key) {
+ return (unsigned)(Key.val * 37);
+ }
+ static bool isEqual(const DupKey& LHS, const DupKey& RHS) {
+ return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey &&
+ LHS.val == RHS.val;
+ }
+};
+
+// Emits a warning when an element is implicitly set a value that
+// a previous element has already been set to.
+static void CheckForDuplicateEnumValues(Sema &S, Decl **Elements,
+ unsigned NumElements, EnumDecl *Enum,
+ QualType EnumType) {
+ if (S.Diags.getDiagnosticLevel(diag::warn_duplicate_enum_values,
+ Enum->getLocation()) ==
+ DiagnosticsEngine::Ignored)
+ return;
+ // Avoid anonymous enums
+ if (!Enum->getIdentifier())
+ return;
+
+ // Only check for small enums.
+ if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64)
+ return;
+
+ typedef SmallVector<EnumConstantDecl *, 3> ECDVector;
+ typedef SmallVector<ECDVector *, 3> DuplicatesVector;
+
+ typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector;
+ typedef llvm::DenseMap<DupKey, DeclOrVector, DenseMapInfoDupKey>
+ ValueToVectorMap;
+
+ DuplicatesVector DupVector;
+ ValueToVectorMap EnumMap;
+
+ // Populate the EnumMap with all values represented by enum constants without
+ // an initialier.
+ for (unsigned i = 0; i < NumElements; ++i) {
+ EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+
+ // Null EnumConstantDecl means a previous diagnostic has been emitted for
+ // this constant. Skip this enum since it may be ill-formed.
+ if (!ECD) {
+ return;
+ }
+
+ if (ECD->getInitExpr())
+ continue;
+
+ DupKey Key = GetDupKey(ECD->getInitVal());
+ DeclOrVector &Entry = EnumMap[Key];
+
+ // First time encountering this value.
+ if (Entry.isNull())
+ Entry = ECD;
+ }
+
+ // Create vectors for any values that has duplicates.
+ for (unsigned i = 0; i < NumElements; ++i) {
+ EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+ if (!ValidDuplicateEnum(ECD, Enum))
+ continue;
+
+ DupKey Key = GetDupKey(ECD->getInitVal());
+
+ DeclOrVector& Entry = EnumMap[Key];
+ if (Entry.isNull())
+ continue;
+
+ if (EnumConstantDecl *D = Entry.dyn_cast<EnumConstantDecl*>()) {
+ // Ensure constants are different.
+ if (D == ECD)
+ continue;
+
+ // Create new vector and push values onto it.
+ ECDVector *Vec = new ECDVector();
+ Vec->push_back(D);
+ Vec->push_back(ECD);
+
+ // Update entry to point to the duplicates vector.
+ Entry = Vec;
+
+ // Store the vector somewhere we can consult later for quick emission of
+ // diagnostics.
+ DupVector.push_back(Vec);
+ continue;
+ }
+
+ ECDVector *Vec = Entry.get<ECDVector*>();
+ // Make sure constants are not added more than once.
+ if (*Vec->begin() == ECD)
+ continue;
+
+ Vec->push_back(ECD);
+ }
+
+ // Emit diagnostics.
+ for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(),
+ DupVectorEnd = DupVector.end();
+ DupVectorIter != DupVectorEnd; ++DupVectorIter) {
+ ECDVector *Vec = *DupVectorIter;
+ assert(Vec->size() > 1 && "ECDVector should have at least 2 elements.");
+
+ // Emit warning for one enum constant.
+ ECDVector::iterator I = Vec->begin();
+ S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values)
+ << (*I)->getName() << (*I)->getInitVal().toString(10)
+ << (*I)->getSourceRange();
+ ++I;
+
+ // Emit one note for each of the remaining enum constants with
+ // the same value.
+ for (ECDVector::iterator E = Vec->end(); I != E; ++I)
+ S.Diag((*I)->getLocation(), diag::note_duplicate_element)
+ << (*I)->getName() << (*I)->getInitVal().toString(10)
+ << (*I)->getSourceRange();
+ delete Vec;
+ }
+}
+
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
SourceLocation RBraceLoc, Decl *EnumDeclX,
Decl **Elements, unsigned NumElements,
@@ -10944,6 +11829,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// it needs to go into the function scope.
if (InFunctionDeclarator)
DeclsInPrototypeScope.push_back(Enum);
+
+ CheckForDuplicateEnumValues(*this, Elements, NumElements, Enum, EnumType);
+
+ // Now that the enum type is defined, ensure it's not been underaligned.
+ if (Enum->hasAttrs())
+ CheckAlignasUnderalignment(Enum);
}
Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
@@ -10967,7 +11858,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
if (!Mod)
return true;
- llvm::SmallVector<SourceLocation, 2> IdentifierLocs;
+ SmallVector<SourceLocation, 2> IdentifierLocs;
Module *ModCheck = Mod;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
// If we've run out of module parents, just drop the remaining identifiers.
@@ -10987,6 +11878,19 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
return Import;
}
+void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) {
+ // Create the implicit import declaration.
+ TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
+ ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
+ Loc, Mod, Loc);
+ TU->addDecl(ImportD);
+ Consumer.HandleImplicitImportDecl(ImportD);
+
+ // Make the module visible.
+ PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
+ /*Complain=*/false);
+}
+
void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
IdentifierInfo* AliasName,
SourceLocation PragmaLoc,
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index e326a20c87d0..982e7a5dd81b 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -16,14 +16,17 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/Mangle.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace sema;
@@ -37,6 +40,7 @@ enum AttributeDeclKind {
ExpectedFunctionOrMethod,
ExpectedParameter,
ExpectedFunctionMethodOrBlock,
+ ExpectedFunctionMethodOrClass,
ExpectedFunctionMethodOrParameter,
ExpectedClass,
ExpectedVariable,
@@ -44,7 +48,11 @@ enum AttributeDeclKind {
ExpectedVariableFunctionOrLabel,
ExpectedFieldOrGlobalVar,
ExpectedStruct,
- ExpectedTLSVar
+ ExpectedVariableFunctionOrTag,
+ ExpectedTLSVar,
+ ExpectedVariableOrField,
+ ExpectedVariableFieldOrTag,
+ ExpectedTypeOrNamespace
};
//===----------------------------------------------------------------------===//
@@ -293,12 +301,12 @@ static bool isIntOrBool(Expr *Exp) {
static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
DeclContextLookupConstResult Res1 = RT->getDecl()->lookup(
S.Context.DeclarationNames.getCXXOperatorName(OO_Star));
- if (Res1.first == Res1.second)
+ if (Res1.empty())
return false;
DeclContextLookupConstResult Res2 = RT->getDecl()->lookup(
S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow));
- if (Res2.first == Res2.second)
+ if (Res2.empty())
return false;
return true;
@@ -503,18 +511,22 @@ static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkGuardedVarAttrCommon(S, D, Attr))
return;
- D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ GuardedVarAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handlePtGuardedVarAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+ const AttributeList &Attr) {
if (!checkGuardedVarAttrCommon(S, D, Attr))
return;
if (!threadSafetyCheckIsPointer(S, D, Attr))
return;
- D->addAttr(::new (S.Context) PtGuardedVarAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ PtGuardedVarAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
@@ -594,11 +606,13 @@ static void handleScopedLockableAttr(Sema &S, Decl *D,
if (!checkLockableAttrCommon(S, D, Attr))
return;
- D->addAttr(::new (S.Context) ScopedLockableAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ScopedLockableAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
-static void handleNoThreadSafetyAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,
+ const AttributeList &Attr) {
assert(!Attr.isInvalid());
if (!checkAttributeNumArgs(S, Attr, 0))
@@ -614,7 +628,7 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D,
S.Context));
}
-static void handleNoAddressSafetyAttr(Sema &S, Decl *D,
+static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
assert(!Attr.isInvalid());
@@ -622,13 +636,48 @@ static void handleNoAddressSafetyAttr(Sema &S, Decl *D,
return;
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedFunctionOrMethod;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ NoSanitizeAddressAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleNoSanitizeMemory(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ assert(!Attr.isInvalid());
+
+ if (!checkAttributeNumArgs(S, Attr, 0))
+ return;
+
+ if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedFunctionOrMethod;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(),
+ S.Context));
+}
+
+static void handleNoSanitizeThread(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ assert(!Attr.isInvalid());
+
+ if (!checkAttributeNumArgs(S, Attr, 0))
+ return;
+
+ if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
- D->addAttr(::new (S.Context) NoAddressSafetyAnalysisAttr(Attr.getRange(),
- S.Context));
+ D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(),
+ S.Context));
}
static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
@@ -673,8 +722,10 @@ static void handleAcquiredAfterAttr(Sema &S, Decl *D,
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getRange(), S.Context,
- StartArg, Args.size()));
+ D->addAttr(::new (S.Context)
+ AcquiredAfterAttr(Attr.getRange(), S.Context,
+ StartArg, Args.size(),
+ Attr.getAttributeSpellingListIndex()));
}
static void handleAcquiredBeforeAttr(Sema &S, Decl *D,
@@ -684,8 +735,10 @@ static void handleAcquiredBeforeAttr(Sema &S, Decl *D,
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context,
- StartArg, Args.size()));
+ D->addAttr(::new (S.Context)
+ AcquiredBeforeAttr(Attr.getRange(), S.Context,
+ StartArg, Args.size(),
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkLockFunAttrCommon(Sema &S, Decl *D,
@@ -716,9 +769,9 @@ static void handleSharedLockFunctionAttr(Sema &S, Decl *D,
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context) SharedLockFunctionAttr(Attr.getRange(),
- S.Context,
- StartArg, Size));
+ D->addAttr(::new (S.Context)
+ SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D,
@@ -729,9 +782,10 @@ static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D,
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getRange(),
- S.Context,
- StartArg, Size));
+ D->addAttr(::new (S.Context)
+ ExclusiveLockFunctionAttr(Attr.getRange(), S.Context,
+ StartArg, Size,
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
@@ -768,10 +822,10 @@ static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(),
- S.Context,
- Attr.getArg(0),
- StartArg, Size));
+ D->addAttr(::new (S.Context)
+ SharedTrylockFunctionAttr(Attr.getRange(), S.Context,
+ Attr.getArg(0), StartArg, Size,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
@@ -782,10 +836,10 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(),
- S.Context,
- Attr.getArg(0),
- StartArg, Size));
+ D->addAttr(::new (S.Context)
+ ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context,
+ Attr.getArg(0), StartArg, Size,
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkLocksRequiredCommon(Sema &S, Decl *D,
@@ -817,10 +871,10 @@ static void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D,
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(),
- S.Context,
- StartArg,
- Args.size()));
+ D->addAttr(::new (S.Context)
+ ExclusiveLocksRequiredAttr(Attr.getRange(), S.Context,
+ StartArg, Args.size(),
+ Attr.getAttributeSpellingListIndex()));
}
static void handleSharedLocksRequiredAttr(Sema &S, Decl *D,
@@ -830,10 +884,10 @@ static void handleSharedLocksRequiredAttr(Sema &S, Decl *D,
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getRange(),
- S.Context,
- StartArg,
- Args.size()));
+ D->addAttr(::new (S.Context)
+ SharedLocksRequiredAttr(Attr.getRange(), S.Context,
+ StartArg, Args.size(),
+ Attr.getAttributeSpellingListIndex()));
}
static void handleUnlockFunAttr(Sema &S, Decl *D,
@@ -854,8 +908,9 @@ static void handleUnlockFunAttr(Sema &S, Decl *D,
unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getRange(), S.Context,
- StartArg, Size));
+ D->addAttr(::new (S.Context)
+ UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleLockReturnedAttr(Sema &S, Decl *D,
@@ -878,8 +933,9 @@ static void handleLockReturnedAttr(Sema &S, Decl *D,
if (Size == 0)
return;
- D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getRange(), S.Context,
- Args[0]));
+ D->addAttr(::new (S.Context)
+ LockReturnedAttr(Attr.getRange(), S.Context, Args[0],
+ Attr.getAttributeSpellingListIndex()));
}
static void handleLocksExcludedAttr(Sema &S, Decl *D,
@@ -903,54 +959,24 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D,
return;
Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getRange(), S.Context,
- StartArg, Size));
+ D->addAttr(::new (S.Context)
+ LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr) {
- TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(D);
- if (tDecl == 0) {
+ TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+ if (TD == 0) {
+ // __attribute__((ext_vector_type(N))) can only be applied to typedefs
+ // and type-ids.
S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
return;
}
- QualType curType = tDecl->getUnderlyingType();
-
- Expr *sizeExpr;
-
- // Special case where the argument is a template id.
- if (Attr.getParameterName()) {
- CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
- UnqualifiedId id;
- id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
-
- ExprResult Size = S.ActOnIdExpression(scope, SS, TemplateKWLoc, id,
- false, false);
- if (Size.isInvalid())
- return;
-
- sizeExpr = Size.get();
- } else {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 1))
- return;
-
- sizeExpr = Attr.getArg(0);
- }
-
- // Instantiate/Install the vector type, and let Sema build the type for us.
- // This will run the reguired checks.
- QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc());
- if (!T.isNull()) {
- // FIXME: preserve the old source info.
- tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T));
-
- // Remember this typedef decl, we will need it later for diagnostics.
- S.ExtVectorDecls.push_back(tDecl);
- }
+ // Remember this typedef decl, we will need it later for diagnostics.
+ S.ExtVectorDecls.push_back(TD);
}
static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -969,14 +995,18 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
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));
+ FD->addAttr(::new (S.Context)
+ PackedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (RecordDecl *RD = dyn_cast<RecordDecl>(D))
- RD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context));
+ RD->addAttr(::new (S.Context)
+ MsStructAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
@@ -989,7 +1019,9 @@ static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) {
// The IBAction attributes only apply to instance methods.
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
if (MD->isInstanceMethod()) {
- D->addAttr(::new (S.Context) IBActionAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ IBActionAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
}
@@ -1030,7 +1062,9 @@ static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkIBOutletCommon(S, D, Attr))
return;
- D->addAttr(::new (S.Context) IBOutletAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ IBOutletAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleIBOutletCollection(Sema &S, Decl *D,
@@ -1064,8 +1098,10 @@ static void handleIBOutletCollection(Sema &S, Decl *D,
S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
return;
}
- D->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getRange(),S.Context,
- QT, Attr.getParameterLoc()));
+ D->addAttr(::new (S.Context)
+ IBOutletCollectionAttr(Attr.getRange(),S.Context,
+ QT, Attr.getParameterLoc(),
+ Attr.getAttributeSpellingListIndex()));
}
static void possibleTransparentUnionPointerType(QualType &T) {
@@ -1096,7 +1132,11 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// In C++ the implicit 'this' function parameter also counts, and they are
// counted from one.
bool HasImplicitThisParam = isInstanceMethod(D);
- unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
+ unsigned NumArgs;
+ if (hasFunctionProto(D))
+ NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
+ else
+ NumArgs = 0;
SmallVector<unsigned, 8> SizeArgs;
@@ -1148,8 +1188,10 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
<< "alloc_size" << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange();
}
- D->addAttr(::new (S.Context) AllocSizeAttr(Attr.getRange(), S.Context,
- SizeArgs.data(), SizeArgs.size()));
+ D->addAttr(::new (S.Context)
+ AllocSizeAttr(Attr.getRange(), S.Context,
+ SizeArgs.data(), SizeArgs.size(),
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1164,15 +1206,13 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// In C++ the implicit 'this' function parameter also counts, and they are
// counted from one.
bool HasImplicitThisParam = isInstanceMethod(D);
- unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
+ unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
// The nonnull attribute only applies to pointers.
SmallVector<unsigned, 10> NonNullArgs;
- for (AttributeList::arg_iterator I=Attr.arg_begin(),
- E=Attr.arg_end(); I!=E; ++I) {
-
-
+ for (AttributeList::arg_iterator I = Attr.arg_begin(),
+ E = Attr.arg_end(); I != E; ++I) {
// The argument must be an integer constant expression.
Expr *Ex = *I;
llvm::APSInt ArgNum(32);
@@ -1219,11 +1259,11 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// If no arguments were specified to __attribute__((nonnull)) then all pointer
// arguments have a nonnull attribute.
if (NonNullArgs.empty()) {
- for (unsigned I = 0, E = getFunctionOrMethodNumArgs(D); I != E; ++I) {
- QualType T = getFunctionOrMethodArgType(D, I).getNonReferenceType();
+ for (unsigned i = 0, e = getFunctionOrMethodNumArgs(D); i != e; ++i) {
+ QualType T = getFunctionOrMethodArgType(D, i).getNonReferenceType();
possibleTransparentUnionPointerType(T);
if (T->isAnyPointerType() || T->isBlockPointerType())
- NonNullArgs.push_back(I);
+ NonNullArgs.push_back(i);
}
// No pointer arguments?
@@ -1236,11 +1276,12 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
}
- unsigned* start = &NonNullArgs[0];
+ unsigned *start = &NonNullArgs[0];
unsigned size = NonNullArgs.size();
llvm::array_pod_sort(start, start + size);
- D->addAttr(::new (S.Context) NonNullAttr(Attr.getRange(), S.Context, start,
- size));
+ D->addAttr(::new (S.Context)
+ NonNullAttr(Attr.getRange(), S.Context, start, size,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
@@ -1395,27 +1436,9 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
return;
}
- D->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
- start, size));
-}
-
-/// Whether this declaration has internal linkage for the purposes of
-/// things that want to complain about things not have internal linkage.
-static bool hasEffectivelyInternalLinkage(NamedDecl *D) {
- switch (D->getLinkage()) {
- case NoLinkage:
- case InternalLinkage:
- return true;
-
- // Template instantiations that go from external to unique-external
- // shouldn't get diagnosed.
- case UniqueExternalLinkage:
- return true;
-
- case ExternalLinkage:
- return false;
- }
- llvm_unreachable("unknown linkage kind!");
+ D->addAttr(::new (S.Context)
+ OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size,
+ AL.getAttributeSpellingListIndex()));
}
static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1468,11 +1491,6 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// This looks like a bug in gcc. We reject that for now. We should revisit
// it if this behaviour is actually used.
- if (!hasEffectivelyInternalLinkage(nd)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static);
- return;
- }
-
// GCC rejects
// static ((alias ("y"), weakref)).
// Should we? How to check that weakref is before or after alias?
@@ -1493,7 +1511,9 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Str->getString()));
}
- D->addAttr(::new (S.Context) WeakRefAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ WeakRefAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1521,7 +1541,8 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// FIXME: check if target symbol exists in current file
D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context,
- Str->getString()));
+ Str->getString(),
+ Attr.getAttributeSpellingListIndex()));
}
static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1535,7 +1556,9 @@ static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) MinSizeAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ MinSizeAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1555,7 +1578,8 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1575,7 +1599,8 @@ static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1589,7 +1614,9 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ NakedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleAlwaysInlineAttr(Sema &S, Decl *D,
@@ -1606,7 +1633,9 @@ static void handleAlwaysInlineAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ AlwaysInlineAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleTLSModelAttr(Sema &S, Decl *D,
@@ -1641,8 +1670,9 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) TLSModelAttr(Attr.getRange(), S.Context,
- Model));
+ D->addAttr(::new (S.Context)
+ TLSModelAttr(Attr.getRange(), S.Context, Model,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1655,7 +1685,9 @@ static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
QualType RetTy = FD->getResultType();
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
- D->addAttr(::new (S.Context) MallocAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ MallocAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
}
}
@@ -1668,13 +1700,17 @@ static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 0))
return;
- D->addAttr(::new (S.Context) MayAliasAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ MayAliasAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
assert(!Attr.isInvalid());
if (isa<VarDecl>(D))
- D->addAttr(::new (S.Context) NoCommonAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ NoCommonAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariable;
@@ -1683,7 +1719,9 @@ static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
assert(!Attr.isInvalid());
if (isa<VarDecl>(D))
- D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CommonAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariable;
@@ -1700,7 +1738,9 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
return;
}
- D->addAttr(::new (S.Context) NoReturnAttr(attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ NoReturnAttr(attr.getRange(), S.Context,
+ attr.getAttributeSpellingListIndex()));
}
bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
@@ -1727,14 +1767,33 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
if (VD == 0 || (!VD->getType()->isBlockPointerType()
&& !VD->getType()->isFunctionPointerType())) {
S.Diag(Attr.getLoc(),
- Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+ Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
: diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionMethodOrBlock;
return;
}
}
- D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ AnalyzerNoReturnAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleCXX11NoReturnAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // C++11 [dcl.attr.noreturn]p1:
+ // The attribute may be applied to the declarator-id in a function
+ // declaration.
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedFunctionOrMethod;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ CXX11NoReturnAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
// PS3 PPU-specific.
@@ -1795,16 +1854,30 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
count++;
}
- D->addAttr(::new (S.Context) VecReturnAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ VecReturnAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
-static void handleDependencyAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isFunctionOrMethod(D) && !isa<ParmVarDecl>(D)) {
+static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
+ const AttributeList &Attr) {
+ if (isa<ParmVarDecl>(D)) {
+ // [[carries_dependency]] can only be applied to a parameter if it is a
+ // parameter of a function declaration or lambda.
+ if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) {
+ S.Diag(Attr.getLoc(),
+ diag::err_carries_dependency_param_not_function_decl);
+ return;
+ }
+ } else if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionMethodOrParameter;
return;
}
- // FIXME: Actually store the attribute on the declaration
+
+ D->addAttr(::new (S.Context) CarriesDependencyAttr(
+ Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1821,7 +1894,9 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) UnusedAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ UnusedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleReturnsTwiceAttr(Sema &S, Decl *D,
@@ -1838,7 +1913,9 @@ static void handleReturnsTwiceAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) ReturnsTwiceAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ReturnsTwiceAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1859,7 +1936,9 @@ static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) UsedAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ UsedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1888,8 +1967,9 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) ConstructorAttr(Attr.getRange(), S.Context,
- priority));
+ D->addAttr(::new (S.Context)
+ ConstructorAttr(Attr.getRange(), S.Context, priority,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -1918,8 +1998,9 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) DestructorAttr(Attr.getRange(), S.Context,
- priority));
+ D->addAttr(::new (S.Context)
+ DestructorAttr(Attr.getRange(), S.Context, priority,
+ Attr.getAttributeSpellingListIndex()));
}
template <typename AttrTy>
@@ -1943,7 +2024,8 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr,
Str = SE->getString();
}
- D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str));
+ D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,
@@ -1954,8 +2036,9 @@ static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) ArcWeakrefUnavailableAttr(
- Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleObjCRootClassAttr(Sema &S, Decl *D,
@@ -1971,11 +2054,13 @@ static void handleObjCRootClassAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) ObjCRootClassAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ObjCRootClassAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
-static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
if (!isa<ObjCInterfaceDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis);
return;
@@ -1987,8 +2072,9 @@ static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) ObjCRequiresPropertyDefsAttr(
- Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
@@ -2030,13 +2116,33 @@ static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
return false;
}
-AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range,
+/// \brief Check whether the two versions match.
+///
+/// If either version tuple is empty, then they are assumed to match. If
+/// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y.
+static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y,
+ bool BeforeIsOkay) {
+ if (X.empty() || Y.empty())
+ return true;
+
+ if (X == Y)
+ return true;
+
+ if (BeforeIsOkay && X < Y)
+ return true;
+
+ return false;
+}
+
+AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
IdentifierInfo *Platform,
VersionTuple Introduced,
VersionTuple Deprecated,
VersionTuple Obsoleted,
bool IsUnavailable,
- StringRef Message) {
+ StringRef Message,
+ bool Override,
+ unsigned AttrSpellingListIndex) {
VersionTuple MergedIntroduced = Introduced;
VersionTuple MergedDeprecated = Deprecated;
VersionTuple MergedObsoleted = Obsoleted;
@@ -2062,18 +2168,47 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range,
VersionTuple OldDeprecated = OldAA->getDeprecated();
VersionTuple OldObsoleted = OldAA->getObsoleted();
bool OldIsUnavailable = OldAA->getUnavailable();
- StringRef OldMessage = OldAA->getMessage();
-
- if ((!OldIntroduced.empty() && !Introduced.empty() &&
- OldIntroduced != Introduced) ||
- (!OldDeprecated.empty() && !Deprecated.empty() &&
- OldDeprecated != Deprecated) ||
- (!OldObsoleted.empty() && !Obsoleted.empty() &&
- OldObsoleted != Obsoleted) ||
- (OldIsUnavailable != IsUnavailable) ||
- (OldMessage != Message)) {
- Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
- Diag(Range.getBegin(), diag::note_previous_attribute);
+
+ if (!versionsMatch(OldIntroduced, Introduced, Override) ||
+ !versionsMatch(Deprecated, OldDeprecated, Override) ||
+ !versionsMatch(Obsoleted, OldObsoleted, Override) ||
+ !(OldIsUnavailable == IsUnavailable ||
+ (Override && !OldIsUnavailable && IsUnavailable))) {
+ if (Override) {
+ int Which = -1;
+ VersionTuple FirstVersion;
+ VersionTuple SecondVersion;
+ if (!versionsMatch(OldIntroduced, Introduced, Override)) {
+ Which = 0;
+ FirstVersion = OldIntroduced;
+ SecondVersion = Introduced;
+ } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) {
+ Which = 1;
+ FirstVersion = Deprecated;
+ SecondVersion = OldDeprecated;
+ } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) {
+ Which = 2;
+ FirstVersion = Obsoleted;
+ SecondVersion = OldObsoleted;
+ }
+
+ if (Which == -1) {
+ Diag(OldAA->getLocation(),
+ diag::warn_mismatched_availability_override_unavail)
+ << AvailabilityAttr::getPrettyPlatformName(Platform->getName());
+ } else {
+ Diag(OldAA->getLocation(),
+ diag::warn_mismatched_availability_override)
+ << Which
+ << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
+ << FirstVersion.getAsString() << SecondVersion.getAsString();
+ }
+ Diag(Range.getBegin(), diag::note_overridden_method);
+ } else {
+ Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
+ Diag(Range.getBegin(), diag::note_previous_attribute);
+ }
+
Attrs.erase(Attrs.begin() + i);
--e;
continue;
@@ -2115,7 +2250,8 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range,
MergedDeprecated, MergedObsoleted)) {
return ::new (Context) AvailabilityAttr(Range, Context, Platform,
Introduced, Deprecated,
- Obsoleted, IsUnavailable, Message);
+ Obsoleted, IsUnavailable, Message,
+ AttrSpellingListIndex);
}
return NULL;
}
@@ -2124,11 +2260,18 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
IdentifierInfo *Platform = Attr.getParameterName();
SourceLocation PlatformLoc = Attr.getParameterLoc();
-
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+
if (AvailabilityAttr::getPrettyPlatformName(Platform->getName()).empty())
S.Diag(PlatformLoc, diag::warn_availability_unknown_platform)
<< Platform;
+ NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ if (!ND) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return;
+ }
+
AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
@@ -2139,37 +2282,69 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
if (SE)
Str = SE->getString();
- AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(D, Attr.getRange(),
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(),
Platform,
Introduced.Version,
Deprecated.Version,
Obsoleted.Version,
- IsUnavailable, Str);
+ IsUnavailable, Str,
+ /*Override=*/false,
+ Index);
if (NewAttr)
D->addAttr(NewAttr);
}
+template <class T>
+static T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range,
+ typename T::VisibilityType value,
+ unsigned attrSpellingListIndex) {
+ T *existingAttr = D->getAttr<T>();
+ if (existingAttr) {
+ typename T::VisibilityType existingValue = existingAttr->getVisibility();
+ if (existingValue == value)
+ return NULL;
+ S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility);
+ S.Diag(range.getBegin(), diag::note_previous_attribute);
+ D->dropAttr<T>();
+ }
+ return ::new (S.Context) T(range, S.Context, value, attrSpellingListIndex);
+}
+
VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range,
- VisibilityAttr::VisibilityType Vis) {
+ VisibilityAttr::VisibilityType Vis,
+ unsigned AttrSpellingListIndex) {
+ return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, Range, Vis,
+ AttrSpellingListIndex);
+}
+
+TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
+ TypeVisibilityAttr::VisibilityType Vis,
+ unsigned AttrSpellingListIndex) {
+ return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, Range, Vis,
+ AttrSpellingListIndex);
+}
+
+static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
+ bool isTypeVisibility) {
+ // Visibility attributes don't mean anything on a typedef.
if (isa<TypedefNameDecl>(D)) {
- Diag(Range.getBegin(), diag::warn_attribute_ignored) << "visibility";
- return NULL;
+ S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored)
+ << Attr.getName();
+ return;
}
- VisibilityAttr *ExistingAttr = D->getAttr<VisibilityAttr>();
- if (ExistingAttr) {
- VisibilityAttr::VisibilityType ExistingVis = ExistingAttr->getVisibility();
- if (ExistingVis == Vis)
- return NULL;
- Diag(ExistingAttr->getLocation(), diag::err_mismatched_visibility);
- Diag(Range.getBegin(), diag::note_previous_attribute);
- D->dropAttr<VisibilityAttr>();
+
+ // 'type_visibility' can only go on a type or namespace.
+ if (isTypeVisibility &&
+ !(isa<TagDecl>(D) ||
+ isa<ObjCInterfaceDecl>(D) ||
+ isa<NamespaceDecl>(D))) {
+ S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedTypeOrNamespace;
+ return;
}
- return ::new (Context) VisibilityAttr(Range, Context, Vis);
-}
-static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
- if(!checkAttributeNumArgs(S, Attr, 1))
+ if (!checkAttributeNumArgs(S, Attr, 1))
return;
Expr *Arg = Attr.getArg(0);
@@ -2178,13 +2353,13 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!Str || !Str->isAscii()) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "visibility" << 1;
+ << (isTypeVisibility ? "type_visibility" : "visibility") << 1;
return;
}
StringRef TypeStr = Str->getString();
VisibilityAttr::VisibilityType type;
-
+
if (TypeStr == "default")
type = VisibilityAttr::Default;
else if (TypeStr == "hidden")
@@ -2205,9 +2380,17 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- VisibilityAttr *NewAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type);
- if (NewAttr)
- D->addAttr(NewAttr);
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ clang::Attr *newAttr;
+ if (isTypeVisibility) {
+ newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(),
+ (TypeVisibilityAttr::VisibilityType) type,
+ Index);
+ } else {
+ newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index);
+ }
+ if (newAttr)
+ D->addAttr(newAttr);
}
static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
@@ -2274,7 +2457,9 @@ static void handleObjCExceptionAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ObjCExceptionAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2305,7 +2490,9 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
// case.
S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
}
- D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ObjCNSObjectAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void
@@ -2320,7 +2507,9 @@ handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) OverloadableAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ OverloadableAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2344,7 +2533,9 @@ static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) BlocksAttr(Attr.getRange(), S.Context, type));
+ D->addAttr(::new (S.Context)
+ BlocksAttr(Attr.getRange(), S.Context, type,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2436,8 +2627,9 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
<< Attr.getName() << ExpectedFunctionMethodOrBlock;
return;
}
- D->addAttr(::new (S.Context) SentinelAttr(Attr.getRange(), S.Context, sentinel,
- nullPos));
+ D->addAttr(::new (S.Context)
+ SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2445,9 +2637,9 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr)
if (!checkAttributeNumArgs(S, Attr, 0))
return;
- if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) {
+ if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
+ << Attr.getName() << ExpectedFunctionMethodOrClass;
return;
}
@@ -2463,7 +2655,9 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr)
return;
}
- D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ WarnUnusedResultAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2485,13 +2679,9 @@ static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {
NamedDecl *nd = cast<NamedDecl>(D);
- // 'weak' only applies to declarations with external linkage.
- if (hasEffectivelyInternalLinkage(nd)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_weak_static);
- return;
- }
-
- nd->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context));
+ nd->addAttr(::new (S.Context)
+ WeakAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2518,7 +2708,9 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) WeakImportAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ WeakImportAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
// Handles reqd_work_group_size and work_group_size_hint.
@@ -2568,15 +2760,57 @@ static void handleWorkGroupSize(Sema &S, Decl *D,
if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize)
D->addAttr(::new (S.Context)
ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context,
- WGSize[0], WGSize[1], WGSize[2]));
+ WGSize[0], WGSize[1], WGSize[2],
+ Attr.getAttributeSpellingListIndex()));
else
D->addAttr(::new (S.Context)
WorkGroupSizeHintAttr(Attr.getRange(), S.Context,
- WGSize[0], WGSize[1], WGSize[2]));
+ WGSize[0], WGSize[1], WGSize[2],
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
+ assert(Attr.getKind() == AttributeList::AT_VecTypeHint);
+
+ // Attribute has 1 argument.
+ if (!checkAttributeNumArgs(S, Attr, 1))
+ return;
+
+ QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg());
+
+ if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
+ (ParmType->isBooleanType() ||
+ !ParmType->isIntegralType(S.getASTContext()))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint)
+ << ParmType;
+ return;
+ }
+
+ if (Attr.getKind() == AttributeList::AT_VecTypeHint &&
+ D->hasAttr<VecTypeHintAttr>()) {
+ VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>();
+ if (A->getTypeHint() != ParmType) {
+ S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
+ return;
+ }
+ }
+
+ D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context,
+ ParmType, Attr.getLoc()));
+}
+
+static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!dyn_cast<VarDecl>(D))
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian"
+ << 9;
+ StringRef EndianType = Attr.getParameterName()->getName();
+ if (EndianType != "host" && EndianType != "device")
+ S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType;
}
SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
- StringRef Name) {
+ StringRef Name,
+ unsigned AttrSpellingListIndex) {
if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
if (ExistingAttr->getName() == Name)
return NULL;
@@ -2584,7 +2818,8 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
Diag(Range.getBegin(), diag::note_previous_attribute);
return NULL;
}
- return ::new (Context) SectionAttr(Range, Context, Name);
+ return ::new (Context) SectionAttr(Range, Context, Name,
+ AttrSpellingListIndex);
}
static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2614,8 +2849,10 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable);
return;
}
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(),
- SE->getString());
+ SE->getString(), Index);
if (NewAttr)
D->addAttr(NewAttr);
}
@@ -2632,7 +2869,9 @@ static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Existing->getLocation().isInvalid())
Existing->setRange(Attr.getRange());
} else {
- D->addAttr(::new (S.Context) NoThrowAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ NoThrowAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
}
@@ -2647,7 +2886,9 @@ static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Existing->getLocation().isInvalid())
Existing->setRange(Attr.getRange());
} else {
- D->addAttr(::new (S.Context) ConstAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ConstAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex() ));
}
}
@@ -2656,7 +2897,9 @@ static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 0))
return;
- D->addAttr(::new (S.Context) PureAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ PureAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2715,8 +2958,11 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD));
+ D->addAttr(::new (S.Context)
+ CleanupAttr(Attr.getRange(), S.Context, FD,
+ Attr.getAttributeSpellingListIndex()));
S.MarkFunctionReferenced(Attr.getParameterLoc(), FD);
+ S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc());
}
/// Handle __attribute__((format_arg((idx)))) attribute based on
@@ -2790,8 +3036,9 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) FormatArgAttr(Attr.getRange(), S.Context,
- Idx.getZExtValue()));
+ D->addAttr(::new (S.Context)
+ FormatArgAttr(Attr.getRange(), S.Context, Idx.getZExtValue(),
+ Attr.getAttributeSpellingListIndex()));
}
enum FormatAttrKind {
@@ -2866,12 +3113,14 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,
Attr.setInvalid();
return;
}
- D->addAttr(::new (S.Context) InitPriorityAttr(Attr.getRange(), S.Context,
- prioritynum));
+ D->addAttr(::new (S.Context)
+ InitPriorityAttr(Attr.getRange(), S.Context, prioritynum,
+ Attr.getAttributeSpellingListIndex()));
}
FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format,
- int FormatIdx, int FirstArg) {
+ int FormatIdx, int FirstArg,
+ unsigned AttrSpellingListIndex) {
// Check whether we already have an equivalent format attribute.
for (specific_attr_iterator<FormatAttr>
i = D->specific_attr_begin<FormatAttr>(),
@@ -2889,8 +3138,8 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format,
}
}
- return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx,
- FirstArg);
+ return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, FirstArg,
+ AttrSpellingListIndex);
}
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
@@ -3030,7 +3279,8 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), Format,
Idx.getZExtValue(),
- FirstArg.getZExtValue());
+ FirstArg.getZExtValue(),
+ Attr.getAttributeSpellingListIndex());
if (NewAttr)
D->addAttr(NewAttr);
}
@@ -3099,7 +3349,9 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,
}
}
- RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getRange(), S.Context));
+ RD->addAttr(::new (S.Context)
+ TransparentUnionAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -3124,8 +3376,10 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if ((*i)->getAnnotation() == SE->getString())
return;
}
- D->addAttr(::new (S.Context) AnnotateAttr(Attr.getRange(), S.Context,
- SE->getString()));
+
+ D->addAttr(::new (S.Context)
+ AnnotateAttr(Attr.getRange(), S.Context, SE->getString(),
+ Attr.getAttributeSpellingListIndex()));
}
static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -3135,34 +3389,77 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- //FIXME: The C++0x version of this attribute has more limited applicabilty
- // than GNU's, and should error out when it is used to specify a
- // weaker alignment, rather than being silently ignored.
-
if (Attr.getNumArgs() == 0) {
- D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context,
- true, 0, Attr.isDeclspecAttribute()));
+ D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context,
+ true, 0, Attr.getAttributeSpellingListIndex()));
return;
}
- S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0),
- Attr.isDeclspecAttribute());
-}
+ Expr *E = Attr.getArg(0);
+ if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
+ S.Diag(Attr.getEllipsisLoc(),
+ diag::err_pack_expansion_without_parameter_packs);
+ return;
+ }
-void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
- bool isDeclSpec) {
- // FIXME: Handle pack-expansions here.
- if (DiagnoseUnexpandedParameterPack(E))
+ if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
return;
+ S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(),
+ Attr.isPackExpansion());
+}
+
+void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
+ unsigned SpellingListIndex, bool IsPackExpansion) {
+ AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex);
+ SourceLocation AttrLoc = AttrRange.getBegin();
+
+ // C++11 alignas(...) and C11 _Alignas(...) have additional requirements.
+ if (TmpAttr.isAlignas()) {
+ // C++11 [dcl.align]p1:
+ // An alignment-specifier may be applied to a variable or to a class
+ // data member, but it shall not be applied to a bit-field, a function
+ // parameter, the formal parameter of a catch clause, or a variable
+ // declared with the register storage class specifier. An
+ // alignment-specifier may also be applied to the declaration of a class
+ // or enumeration type.
+ // C11 6.7.5/2:
+ // An alignment attribute shall not be specified in a declaration of
+ // a typedef, or a bit-field, or a function, or a parameter, or an
+ // object declared with the register storage-class specifier.
+ int DiagKind = -1;
+ if (isa<ParmVarDecl>(D)) {
+ DiagKind = 0;
+ } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->getStorageClass() == SC_Register)
+ DiagKind = 1;
+ if (VD->isExceptionVariable())
+ DiagKind = 2;
+ } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+ if (FD->isBitField())
+ DiagKind = 3;
+ } else if (!isa<TagDecl>(D)) {
+ Diag(AttrLoc, diag::err_attribute_wrong_decl_type)
+ << (TmpAttr.isC11() ? "'_Alignas'" : "'alignas'")
+ << (TmpAttr.isC11() ? ExpectedVariableOrField
+ : ExpectedVariableFieldOrTag);
+ return;
+ }
+ if (DiagKind != -1) {
+ Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type)
+ << TmpAttr.isC11() << DiagKind;
+ return;
+ }
+ }
+
if (E->isTypeDependent() || E->isValueDependent()) {
// Save dependent expressions in the AST to be instantiated.
- D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E,
- isDeclSpec));
+ AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr);
+ AA->setPackExpansion(IsPackExpansion);
+ D->addAttr(AA);
return;
}
-
- SourceLocation AttrLoc = AttrRange.getBegin();
+
// FIXME: Cache the number on the Attr object?
llvm::APSInt Alignment(32);
ExprResult ICE
@@ -3171,32 +3468,79 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
/*AllowFold*/ false);
if (ICE.isInvalid())
return;
- if (!llvm::isPowerOf2_64(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) &&
+ !llvm::isPowerOf2_64(Alignment.getZExtValue())) {
Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two)
<< E->getSourceRange();
return;
}
- if (isDeclSpec) {
+
+ if (TmpAttr.isDeclspec()) {
// We've already verified it's a power of 2, now let's make sure it's
// 8192 or less.
if (Alignment.getZExtValue() > 8192) {
- Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192)
+ Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192)
<< E->getSourceRange();
return;
}
}
- D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take(),
- isDeclSpec));
+ AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true,
+ ICE.take(), SpellingListIndex);
+ AA->setPackExpansion(IsPackExpansion);
+ D->addAttr(AA);
}
-void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS,
- bool isDeclSpec) {
+void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS,
+ unsigned SpellingListIndex, bool IsPackExpansion) {
// FIXME: Cache the number on the Attr object if non-dependent?
// FIXME: Perform checking of type validity
- D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS,
- isDeclSpec));
- return;
+ AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS,
+ SpellingListIndex);
+ AA->setPackExpansion(IsPackExpansion);
+ D->addAttr(AA);
+}
+
+void Sema::CheckAlignasUnderalignment(Decl *D) {
+ assert(D->hasAttrs() && "no attributes on decl");
+
+ QualType Ty;
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+ Ty = VD->getType();
+ else
+ Ty = Context.getTagDeclType(cast<TagDecl>(D));
+ if (Ty->isDependentType() || Ty->isIncompleteType())
+ return;
+
+ // C++11 [dcl.align]p5, C11 6.7.5/4:
+ // The combined effect of all alignment attributes in a declaration shall
+ // not specify an alignment that is less strict than the alignment that
+ // would otherwise be required for the entity being declared.
+ AlignedAttr *AlignasAttr = 0;
+ unsigned Align = 0;
+ for (specific_attr_iterator<AlignedAttr>
+ I = D->specific_attr_begin<AlignedAttr>(),
+ E = D->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ if (I->isAlignmentDependent())
+ return;
+ if (I->isAlignas())
+ AlignasAttr = *I;
+ Align = std::max(Align, I->getAlignment(Context));
+ }
+
+ if (AlignasAttr && Align) {
+ CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align);
+ CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty);
+ if (NaturalAlign > RequestedAlign)
+ Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned)
+ << Ty << (unsigned)NaturalAlign.getQuantity();
+ }
}
/// handleModeAttr - This attribute modifies the width of a decl with primitive
@@ -3260,6 +3604,10 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Str == "pointer")
DestWidth = S.Context.getTargetInfo().getPointerWidth(0);
break;
+ case 11:
+ if (Str == "unwind_word")
+ DestWidth = S.Context.getTargetInfo().getUnwindWordWidth();
+ break;
}
QualType OldTy;
@@ -3386,7 +3734,9 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) NoDebugAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ NoDebugAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -3401,7 +3751,9 @@ static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) NoInlineAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ NoInlineAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
@@ -3417,8 +3769,9 @@ static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getRange(),
- S.Context));
+ D->addAttr(::new (S.Context)
+ NoInstrumentFunctionAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -3435,7 +3788,9 @@ static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CUDAConstantAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant";
}
@@ -3455,7 +3810,9 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CUDADeviceAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device";
}
@@ -3476,10 +3833,10 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
FunctionDecl *FD = cast<FunctionDecl>(D);
if (!FD->getResultType()->isVoidType()) {
TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
- if (FunctionTypeLoc* FTL = dyn_cast<FunctionTypeLoc>(&TL)) {
+ if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
<< FD->getType()
- << FixItHint::CreateReplacement(FTL->getResultLoc().getSourceRange(),
+ << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(),
"void");
} else {
S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
@@ -3488,7 +3845,9 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CUDAGlobalAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global";
}
@@ -3507,7 +3866,9 @@ static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) CUDAHostAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CUDAHostAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host";
}
@@ -3519,14 +3880,15 @@ static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 0))
return;
-
if (!isa<VarDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariable;
return;
}
- D->addAttr(::new (S.Context) CUDASharedAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CUDASharedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared";
}
@@ -3549,16 +3911,19 @@ static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) GNUInlineAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ GNUInlineAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (hasDeclarator(D)) return;
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
// Diagnostic is emitted elsewhere: here we store the (valid) Attr
// in the Decl node for syntactic reasoning, e.g., pretty-printing.
CallingConv CC;
- if (S.CheckCallingConvAttr(Attr, CC))
+ if (S.CheckCallingConvAttr(Attr, CC, FD))
return;
if (!isa<ObjCMethodDecl>(D)) {
@@ -3569,19 +3934,29 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
switch (Attr.getKind()) {
case AttributeList::AT_FastCall:
- D->addAttr(::new (S.Context) FastCallAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ FastCallAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_StdCall:
- D->addAttr(::new (S.Context) StdCallAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ StdCallAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_ThisCall:
- D->addAttr(::new (S.Context) ThisCallAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ThisCallAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_CDecl:
- D->addAttr(::new (S.Context) CDeclAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CDeclAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_Pascal:
- D->addAttr(::new (S.Context) PascalAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ PascalAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_Pcs: {
PcsAttr::PCSType PCS;
@@ -3596,11 +3971,20 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
llvm_unreachable("unexpected calling convention in pcs attribute");
}
- D->addAttr(::new (S.Context) PcsAttr(Attr.getRange(), S.Context, PCS));
+ D->addAttr(::new (S.Context)
+ PcsAttr(Attr.getRange(), S.Context, PCS,
+ Attr.getAttributeSpellingListIndex()));
return;
}
case AttributeList::AT_PnaclCall:
- D->addAttr(::new (S.Context) PnaclCallAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ PnaclCallAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+ return;
+ case AttributeList::AT_IntelOclBicc:
+ D->addAttr(::new (S.Context)
+ IntelOclBiccAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
default:
@@ -3613,7 +3997,24 @@ static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){
D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context));
}
-bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
+static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){
+ assert(!Attr.isInvalid());
+
+ Expr *E = Attr.getArg(0);
+ llvm::APSInt ArgNum(32);
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ !E->isIntegerConstantExpr(ArgNum, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << Attr.getName()->getName() << E->getSourceRange();
+ return;
+ }
+
+ D->addAttr(::new (S.Context) OpenCLImageAccessAttr(
+ Attr.getRange(), S.Context, ArgNum.getZExtValue()));
+}
+
+bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
+ const FunctionDecl *FD) {
if (attr.isInvalid())
return true;
@@ -3656,6 +4057,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
return true;
}
case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break;
+ case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break;
default: llvm_unreachable("unexpected attribute kind");
}
@@ -3663,7 +4065,12 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);
if (A == TargetInfo::CCCR_Warning) {
Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName();
- CC = TI.getDefaultCallingConv();
+
+ TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown;
+ if (FD)
+ MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member :
+ TargetInfo::CCMT_NonMember;
+ CC = TI.getDefaultCallingConv(MT);
}
return false;
@@ -3682,7 +4089,9 @@ static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- D->addAttr(::new (S.Context) RegparmAttr(Attr.getRange(), S.Context, numParams));
+ D->addAttr(::new (S.Context)
+ RegparmAttr(Attr.getRange(), S.Context, numParams,
+ Attr.getAttributeSpellingListIndex()));
}
/// Checks a regparm attribute, returning true if it is ill-formed and
@@ -3762,9 +4171,11 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
}
}
- D->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
- MaxThreads.getZExtValue(),
- MinBlocks.getZExtValue()));
+ D->addAttr(::new (S.Context)
+ CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
+ MaxThreads.getZExtValue(),
+ MinBlocks.getZExtValue(),
+ Attr.getAttributeSpellingListIndex()));
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds";
}
@@ -3815,12 +4226,10 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
}
}
- D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(Attr.getRange(),
- S.Context,
- ArgumentKind,
- ArgumentIdx,
- TypeTagIdx,
- IsPointer));
+ D->addAttr(::new (S.Context)
+ ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind,
+ ArgumentIdx, TypeTagIdx, IsPointer,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
@@ -3834,13 +4243,12 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL);
- D->addAttr(::new (S.Context) TypeTagForDatatypeAttr(
- Attr.getRange(),
- S.Context,
- PointerKind,
- MatchingCType,
- Attr.getLayoutCompatible(),
- Attr.getMustBeNull()));
+ D->addAttr(::new (S.Context)
+ TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind,
+ MatchingCType,
+ Attr.getLayoutCompatible(),
+ Attr.getMustBeNull(),
+ Attr.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
@@ -3882,9 +4290,13 @@ static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
if (cf)
- param->addAttr(::new (S.Context) CFConsumedAttr(Attr.getRange(), S.Context));
+ param->addAttr(::new (S.Context)
+ CFConsumedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else
- param->addAttr(::new (S.Context) NSConsumedAttr(Attr.getRange(), S.Context));
+ param->addAttr(::new (S.Context)
+ NSConsumedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNSConsumesSelfAttr(Sema &S, Decl *D,
@@ -3895,7 +4307,9 @@ static void handleNSConsumesSelfAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context) NSConsumesSelfAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ NSConsumesSelfAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
@@ -3947,24 +4361,29 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
default:
llvm_unreachable("invalid ownership attribute");
case AttributeList::AT_NSReturnsAutoreleased:
- D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(Attr.getRange(),
- S.Context));
+ D->addAttr(::new (S.Context)
+ NSReturnsAutoreleasedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_CFReturnsNotRetained:
- D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getRange(),
- S.Context));
+ D->addAttr(::new (S.Context)
+ CFReturnsNotRetainedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_NSReturnsNotRetained:
- D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getRange(),
- S.Context));
+ D->addAttr(::new (S.Context)
+ NSReturnsNotRetainedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_CFReturnsRetained:
- D->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getRange(),
- S.Context));
+ D->addAttr(::new (S.Context)
+ CFReturnsRetainedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_NSReturnsRetained:
- D->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getRange(),
- S.Context));
+ D->addAttr(::new (S.Context)
+ NSReturnsRetainedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
return;
};
}
@@ -3994,8 +4413,9 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
return;
}
- method->addAttr(
- ::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context));
+ method->addAttr(::new (S.Context)
+ ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context,
+ attr.getAttributeSpellingListIndex()));
}
static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
@@ -4021,8 +4441,9 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
return;
}
- method->addAttr(
- ::new (S.Context) ObjCRequiresSuperAttr(attr.getRange(), S.Context));
+ method->addAttr(::new (S.Context)
+ ObjCRequiresSuperAttr(attr.getRange(), S.Context,
+ attr.getAttributeSpellingListIndex()));
}
/// Handle cf_audited_transfer and cf_unknown_transfer.
@@ -4052,11 +4473,13 @@ static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) {
// All clear; add the attribute.
if (IsAudited) {
- D->addAttr(
- ::new (S.Context) CFAuditedTransferAttr(A.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CFAuditedTransferAttr(A.getRange(), S.Context,
+ A.getAttributeSpellingListIndex()));
} else {
- D->addAttr(
- ::new (S.Context) CFUnknownTransferAttr(A.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ CFUnknownTransferAttr(A.getRange(), S.Context,
+ A.getAttributeSpellingListIndex()));
}
}
@@ -4086,8 +4509,9 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,
}
}
- D->addAttr(::new (S.Context) NSBridgedAttr(Attr.getRange(), S.Context,
- ParmName));
+ D->addAttr(::new (S.Context)
+ NSBridgedAttr(Attr.getRange(), S.Context, ParmName,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleObjCOwnershipAttr(Sema &S, Decl *D,
@@ -4141,7 +4565,8 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
}
D->addAttr(::new (S.Context)
- ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context));
+ ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
//===----------------------------------------------------------------------===//
@@ -4189,15 +4614,16 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
return;
}
- } else if (!isxdigit(*I)) {
+ } else if (!isHexDigit(*I)) {
S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
return;
}
I++;
}
- D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context,
- Str->getString()));
+ D->addAttr(::new (S.Context)
+ UuidAttr(Attr.getRange(), S.Context, Str->getString(),
+ Attr.getAttributeSpellingListIndex()));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid";
}
@@ -4211,13 +4637,19 @@ static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
AttributeList::Kind Kind = Attr.getKind();
if (Kind == AttributeList::AT_SingleInheritance)
D->addAttr(
- ::new (S.Context) SingleInheritanceAttr(Attr.getRange(), S.Context));
+ ::new (S.Context)
+ SingleInheritanceAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else if (Kind == AttributeList::AT_MultipleInheritance)
D->addAttr(
- ::new (S.Context) MultipleInheritanceAttr(Attr.getRange(), S.Context));
+ ::new (S.Context)
+ MultipleInheritanceAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else if (Kind == AttributeList::AT_VirtualInheritance)
D->addAttr(
- ::new (S.Context) VirtualInheritanceAttr(Attr.getRange(), S.Context));
+ ::new (S.Context)
+ VirtualInheritanceAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -4225,20 +4657,25 @@ static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
AttributeList::Kind Kind = Attr.getKind();
if (Kind == AttributeList::AT_Ptr32)
D->addAttr(
- ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context));
+ ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else if (Kind == AttributeList::AT_Ptr64)
D->addAttr(
- ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context));
+ ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else if (Kind == AttributeList::AT_Win64)
D->addAttr(
- ::new (S.Context) Win64Attr(Attr.getRange(), S.Context));
+ ::new (S.Context) Win64Attr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.MicrosoftExt)
- D->addAttr(::new (S.Context) ForceInlineAttr(Attr.getRange(), S.Context));
+ D->addAttr(::new (S.Context)
+ ForceInlineAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
@@ -4261,12 +4698,11 @@ static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr) {
switch (Attr.getKind()) {
- case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break;
- case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break;
- case AttributeList::AT_IBOutletCollection:
- handleIBOutletCollection(S, D, Attr); break;
+ case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break;
+ case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break;
+ case AttributeList::AT_IBOutletCollection:
+ handleIBOutletCollection(S, D, Attr); break;
case AttributeList::AT_AddressSpace:
- case AttributeList::AT_OpenCLImageAccess:
case AttributeList::AT_ObjCGC:
case AttributeList::AT_VectorSize:
case AttributeList::AT_NeonVectorType:
@@ -4291,10 +4727,14 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break;
case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break;
case AttributeList::AT_CarriesDependency:
- handleDependencyAttr (S, D, Attr); break;
+ handleDependencyAttr(S, scope, D, Attr);
+ break;
case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break;
case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break;
case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break;
+ case AttributeList::AT_CXX11NoReturn:
+ handleCXX11NoReturnAttr(S, D, Attr);
+ break;
case AttributeList::AT_Deprecated:
handleAttrWithMessage<DeprecatedAttr>(S, D, Attr, "deprecated");
break;
@@ -4364,6 +4804,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ReqdWorkGroupSize:
handleWorkGroupSize(S, D, Attr); break;
+ case AttributeList::AT_VecTypeHint:
+ handleVecTypeHint(S, D, Attr); break;
+
+ case AttributeList::AT_Endian:
+ handleEndianAttr(S, D, Attr);
+ break;
+
case AttributeList::AT_InitPriority:
handleInitPriorityAttr(S, D, Attr); break;
@@ -4386,7 +4833,12 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
handleReturnsTwiceAttr(S, D, Attr);
break;
case AttributeList::AT_Used: handleUsedAttr (S, D, Attr); break;
- case AttributeList::AT_Visibility: handleVisibilityAttr (S, D, Attr); break;
+ case AttributeList::AT_Visibility:
+ handleVisibilityAttr(S, D, Attr, false);
+ break;
+ case AttributeList::AT_TypeVisibility:
+ handleVisibilityAttr(S, D, Attr, true);
+ break;
case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr);
break;
case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break;
@@ -4423,11 +4875,15 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_Pascal:
case AttributeList::AT_Pcs:
case AttributeList::AT_PnaclCall:
+ case AttributeList::AT_IntelOclBicc:
handleCallConvAttr(S, D, Attr);
break;
case AttributeList::AT_OpenCLKernel:
handleOpenCLKernelAttr(S, D, Attr);
break;
+ case AttributeList::AT_OpenCLImageAccess:
+ handleOpenCLImageAccessAttr(S, D, Attr);
+ break;
// Microsoft attributes:
case AttributeList::AT_MsStruct:
@@ -4460,11 +4916,17 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ScopedLockable:
handleScopedLockableAttr(S, D, Attr);
break;
- case AttributeList::AT_NoAddressSafetyAnalysis:
- handleNoAddressSafetyAttr(S, D, Attr);
+ case AttributeList::AT_NoSanitizeAddress:
+ handleNoSanitizeAddressAttr(S, D, Attr);
break;
case AttributeList::AT_NoThreadSafetyAnalysis:
- handleNoThreadSafetyAttr(S, D, Attr);
+ handleNoThreadSafetyAnalysis(S, D, Attr);
+ break;
+ case AttributeList::AT_NoSanitizeThread:
+ handleNoSanitizeThread(S, D, Attr);
+ break;
+ case AttributeList::AT_NoSanitizeMemory:
+ handleNoSanitizeMemory(S, D, Attr);
break;
case AttributeList::AT_Lockable:
handleLockableAttr(S, D, Attr);
@@ -4530,19 +4992,17 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
/// the attribute applies to decls. If the attribute is a type attribute, just
-/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
-/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
+/// silently ignore it if a GNU attribute.
static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr,
- bool NonInheritable, bool Inheritable) {
+ bool NonInheritable, bool Inheritable,
+ bool IncludeCXX11Attributes) {
if (Attr.isInvalid())
return;
- // Type attributes are still treated as declaration attributes by
- // ParseMicrosoftTypeAttributes and ParseBorlandTypeAttributes. We don't
- // want to process them, however, because we will simply warn about ignoring
- // them. So instead, we will bail out early.
- if (Attr.isMSTypespecAttribute())
+ // Ignore C++11 attributes on declarator chunks: they appertain to the type
+ // instead.
+ if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes)
return;
if (NonInheritable)
@@ -4556,17 +5016,19 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
/// attribute list to the specified decl, ignoring any type attributes.
void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
const AttributeList *AttrList,
- bool NonInheritable, bool Inheritable) {
- for (const AttributeList* l = AttrList; l; l = l->getNext()) {
- ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable);
- }
+ bool NonInheritable, bool Inheritable,
+ bool IncludeCXX11Attributes) {
+ for (const AttributeList* l = AttrList; l; l = l->getNext())
+ ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable,
+ IncludeCXX11Attributes);
// GCC accepts
// static int a9 __attribute__((weakref));
// but that looks really pointless. We reject it.
if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
- dyn_cast<NamedDecl>(D)->getNameAsString();
+ cast<NamedDecl>(D)->getNameAsString();
+ D->dropAttr<WeakRefAttr>();
return;
}
}
@@ -4592,7 +5054,7 @@ bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
for ( ; A; A = A->getNext()) {
// Only warn if the attribute is an unignored, non-type attribute.
- if (A->isUsedAsTypeAttr()) continue;
+ if (A->isUsedAsTypeAttr() || A->isInvalid()) continue;
if (A->getKind() == AttributeList::IgnoredAttribute) continue;
if (A->getKind() == AttributeList::UnknownAttribute) {
@@ -4630,8 +5092,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
Loc, Loc, DeclarationName(II),
FD->getType(), FD->getTypeSourceInfo(),
- SC_None, SC_None,
- false/*isInlineSpecified*/,
+ SC_None, false/*isInlineSpecified*/,
FD->hasPrototype(),
false/*isConstexprSpecified*/);
NewD = NewFD;
@@ -4656,8 +5117,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
VD->getInnerLocStart(), VD->getLocation(), II,
VD->getType(), VD->getTypeSourceInfo(),
- VD->getStorageClass(),
- VD->getStorageClassAsWritten());
+ VD->getStorageClass());
if (VD->getQualifier()) {
VarDecl *NewVD = cast<VarDecl>(NewD);
NewVD->setQualifierInfo(VD->getQualifierLoc());
@@ -4689,30 +5149,37 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
}
}
-/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
-/// it, apply them to D. This is a bit tricky because PD can have attributes
-/// specified in many different places, and we need to find and apply them all.
-void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
- bool NonInheritable, bool Inheritable) {
+void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
// It's valid to "forward-declare" #pragma weak, in which case we
// have to do this.
- if (Inheritable) {
- LoadExternalWeakUndeclaredIdentifiers();
- if (!WeakUndeclaredIdentifiers.empty()) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- if (IdentifierInfo *Id = ND->getIdentifier()) {
- llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I
- = WeakUndeclaredIdentifiers.find(Id);
- if (I != WeakUndeclaredIdentifiers.end() && ND->hasLinkage()) {
- WeakInfo W = I->second;
- DeclApplyPragmaWeak(S, ND, W);
- WeakUndeclaredIdentifiers[Id] = W;
- }
+ LoadExternalWeakUndeclaredIdentifiers();
+ if (!WeakUndeclaredIdentifiers.empty()) {
+ NamedDecl *ND = NULL;
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ if (VD->isExternC())
+ ND = VD;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isExternC())
+ ND = FD;
+ if (ND) {
+ if (IdentifierInfo *Id = ND->getIdentifier()) {
+ llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I
+ = WeakUndeclaredIdentifiers.find(Id);
+ if (I != WeakUndeclaredIdentifiers.end()) {
+ WeakInfo W = I->second;
+ DeclApplyPragmaWeak(S, ND, W);
+ WeakUndeclaredIdentifiers[Id] = W;
}
}
}
}
+}
+/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
+/// it, apply them to D. This is a bit tricky because PD can have attributes
+/// specified in many different places, and we need to find and apply them all.
+void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
+ bool NonInheritable, bool Inheritable) {
// Apply decl attributes from the DeclSpec if present.
if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
@@ -4723,7 +5190,8 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
// when X is a decl attribute.
for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
- ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+ ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable,
+ /*IncludeCXX11Attributes=*/false);
// Finally, apply any attributes on the decl itself.
if (const AttributeList *Attrs = PD.getAttributes())
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 16eddf80ae5b..35890e6deb41 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -12,16 +12,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/CXXFieldCollector.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
-#include "clang/AST/CharUnits.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
@@ -30,12 +25,18 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
-#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/ParsedTemplate.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/SmallString.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include <map>
#include <set>
@@ -251,7 +252,7 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
return true;
Arg = Result.takeAs<Expr>();
- CheckImplicitConversions(Arg, EqualLoc);
+ CheckCompletedExpr(Arg, EqualLoc);
Arg = MaybeCreateExprWithCleanups(Arg);
// Okay: add the default argument to the parameter
@@ -351,16 +352,25 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
// parameter pack. If it is specified in a
// parameter-declaration-clause, it shall not occur within a
// declarator or abstract-declarator of a parameter-declaration.
+ bool MightBeFunction = D.isFunctionDeclarationContext();
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = D.getTypeObject(i);
if (chunk.Kind == DeclaratorChunk::Function) {
+ if (MightBeFunction) {
+ // This is a function declaration. It can have default arguments, but
+ // keep looking in case its return type is a function type with default
+ // arguments.
+ MightBeFunction = false;
+ continue;
+ }
for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
ParmVarDecl *Param =
cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param);
if (Param->hasUnparsedDefaultArg()) {
CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
- << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
+ << SourceRange((*Toks)[1].getLocation(),
+ Toks->back().getLocation());
delete Toks;
chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
} else if (Param->getDefaultArg()) {
@@ -369,6 +379,8 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
Param->setDefaultArg(0);
}
}
+ } else if (chunk.Kind != DeclaratorChunk::Paren) {
+ MightBeFunction = false;
}
}
}
@@ -517,19 +529,26 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
diag::err_param_default_argument_member_template_redecl)
<< WhichKind
<< NewParam->getDefaultArgRange();
- } else if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(New)) {
- CXXSpecialMember NewSM = getSpecialMember(Ctor),
- OldSM = getSpecialMember(cast<CXXConstructorDecl>(Old));
- if (NewSM != OldSM) {
- Diag(NewParam->getLocation(),diag::warn_default_arg_makes_ctor_special)
- << NewParam->getDefaultArgRange() << NewSM;
- Diag(Old->getLocation(), diag::note_previous_declaration_special)
- << OldSM;
- }
}
}
}
+ // DR1344: If a default argument is added outside a class definition and that
+ // default argument makes the function a special member function, the program
+ // is ill-formed. This can only happen for constructors.
+ if (isa<CXXConstructorDecl>(New) &&
+ New->getMinRequiredArguments() < Old->getMinRequiredArguments()) {
+ CXXSpecialMember NewSM = getSpecialMember(cast<CXXMethodDecl>(New)),
+ OldSM = getSpecialMember(cast<CXXMethodDecl>(Old));
+ if (NewSM != OldSM) {
+ ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments());
+ assert(NewParam->hasDefaultArg());
+ Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special)
+ << NewParam->getDefaultArgRange() << NewSM;
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
+ }
+
// C++11 [dcl.constexpr]p1: If any declaration of a function or function
// template has a constexpr specifier then all its declarations shall
// contain the constexpr specifier.
@@ -875,7 +894,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
// - its function-body shall be [...] a compound-statement that contains only
CompoundStmt *CompBody = cast<CompoundStmt>(Body);
- llvm::SmallVector<SourceLocation, 4> ReturnStmts;
+ SmallVector<SourceLocation, 4> ReturnStmts;
for (CompoundStmt::body_iterator BodyIt = CompBody->body_begin(),
BodyEnd = CompBody->body_end(); BodyIt != BodyEnd; ++BodyIt) {
switch ((*BodyIt)->getStmtClass()) {
@@ -985,13 +1004,14 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
// C++11 [dcl.constexpr]p4:
// - every constructor involved in initializing non-static data members and
// base class sub-objects shall be a constexpr constructor.
- llvm::SmallVector<PartialDiagnosticAt, 8> Diags;
+ SmallVector<PartialDiagnosticAt, 8> Diags;
if (!Expr::isPotentialConstantExpr(Dcl, Diags)) {
- Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr)
+ Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr)
<< isa<CXXConstructorDecl>(Dcl);
for (size_t I = 0, N = Diags.size(); I != N; ++I)
Diag(Diags[I].first, Diags[I].second);
- return false;
+ // Don't return false here: we allow this for compatibility in
+ // system headers.
}
return true;
@@ -1163,6 +1183,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
/// 'public bar' and 'virtual private baz' are each base-specifiers.
BaseResult
Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+ ParsedAttributes &Attributes,
bool Virtual, AccessSpecifier Access,
ParsedType basetype, SourceLocation BaseLoc,
SourceLocation EllipsisLoc) {
@@ -1174,6 +1195,22 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
if (!Class)
return true;
+ // We do not support any C++11 attributes on base-specifiers yet.
+ // Diagnose any attributes we see.
+ if (!Attributes.empty()) {
+ for (AttributeList *Attr = Attributes.getList(); Attr;
+ Attr = Attr->getNext()) {
+ if (Attr->isInvalid() ||
+ Attr->getKind() == AttributeList::IgnoredAttribute)
+ continue;
+ Diag(Attr->getLoc(),
+ Attr->getKind() == AttributeList::UnknownAttribute
+ ? diag::warn_unknown_attribute_ignored
+ : diag::err_base_specifier_attribute)
+ << Attr->getName();
+ }
+ }
+
TypeSourceInfo *TInfo = 0;
GetTypeFromParser(basetype, &TInfo);
@@ -1274,29 +1311,25 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases,
(CXXBaseSpecifier**)(Bases), NumBases);
}
-static CXXRecordDecl *GetClassForType(QualType T) {
- if (const RecordType *RT = T->getAs<RecordType>())
- return cast<CXXRecordDecl>(RT->getDecl());
- else if (const InjectedClassNameType *ICT = T->getAs<InjectedClassNameType>())
- return ICT->getDecl();
- else
- return 0;
-}
-
/// \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) {
if (!getLangOpts().CPlusPlus)
return false;
- CXXRecordDecl *DerivedRD = GetClassForType(Derived);
+ CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
if (!DerivedRD)
return false;
- CXXRecordDecl *BaseRD = GetClassForType(Base);
+ CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
if (!BaseRD)
return false;
-
+
+ // If either the base or the derived type is invalid, don't try to
+ // check whether one is derived from the other.
+ if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl())
+ return false;
+
// FIXME: instantiate DerivedRD if necessary. We need a PoI for this.
return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
}
@@ -1307,11 +1340,11 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
if (!getLangOpts().CPlusPlus)
return false;
- CXXRecordDecl *DerivedRD = GetClassForType(Derived);
+ CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
if (!DerivedRD)
return false;
- CXXRecordDecl *BaseRD = GetClassForType(Base);
+ CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
if (!BaseRD)
return false;
@@ -1556,7 +1589,7 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) {
/// bitfield width if there is one, 'InitExpr' specifies the initializer if
/// one has been parsed, and 'InitStyle' is set if an in-class initializer is
/// present (but parsing it has been deferred).
-Decl *
+NamedDecl *
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
Expr *BW, const VirtSpecifiers &VS,
@@ -1657,7 +1690,36 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
!isFunc);
- Decl *Member;
+ if (DS.isConstexprSpecified() && isInstField) {
+ SemaDiagnosticBuilder B =
+ Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member);
+ SourceLocation ConstexprLoc = DS.getConstexprSpecLoc();
+ if (InitStyle == ICIS_NoInit) {
+ B << 0 << 0 << FixItHint::CreateReplacement(ConstexprLoc, "const");
+ D.getMutableDeclSpec().ClearConstexprSpec();
+ const char *PrevSpec;
+ unsigned DiagID;
+ bool Failed = D.getMutableDeclSpec().SetTypeQual(DeclSpec::TQ_const, ConstexprLoc,
+ PrevSpec, DiagID, getLangOpts());
+ (void)Failed;
+ assert(!Failed && "Making a constexpr member const shouldn't fail");
+ } else {
+ B << 1;
+ const char *PrevSpec;
+ unsigned DiagID;
+ if (D.getMutableDeclSpec().SetStorageClassSpec(
+ *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID)) {
+ assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable &&
+ "This is the only DeclSpec that should fail to be applied");
+ B << 1;
+ } else {
+ B << 0 << FixItHint::CreateInsertion(ConstexprLoc, "static ");
+ isInstField = false;
+ }
+ }
+ }
+
+ NamedDecl *Member;
if (isInstField) {
CXXScopeSpec &SS = D.getCXXScopeSpec();
@@ -1711,7 +1773,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
InitStyle, AS);
assert(Member && "HandleField never returns null");
} else {
- assert(InitStyle == ICIS_NoInit);
+ assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static);
Member = HandleDeclarator(S, D, TemplateParameterLists);
if (!Member) {
@@ -1795,7 +1857,11 @@ namespace {
public:
typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited;
UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context),
- S(S), VD(VD) {
+ S(S) {
+ if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(VD))
+ this->VD = IFD->getAnonField();
+ else
+ this->VD = VD;
}
void HandleExpr(Expr *E) {
@@ -1812,23 +1878,33 @@ namespace {
if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
if (isa<EnumConstantDecl>(ME->getMemberDecl()))
- return;
+ return;
+
+ // FieldME is the inner-most MemberExpr that is not an anonymous struct
+ // or union.
+ MemberExpr *FieldME = ME;
+
Expr *Base = E;
while (isa<MemberExpr>(Base)) {
- ME = dyn_cast<MemberExpr>(Base);
- if (VarDecl *VarD = dyn_cast<VarDecl>(ME->getMemberDecl()))
- if (VarD->hasGlobalStorage())
- return;
+ ME = cast<MemberExpr>(Base);
+
+ if (isa<VarDecl>(ME->getMemberDecl()))
+ return;
+
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+ if (!FD->isAnonymousStructOrUnion())
+ FieldME = ME;
+
Base = ME->getBase();
}
- if (VD == ME->getMemberDecl() && isa<CXXThisExpr>(Base)) {
+ if (VD == FieldME->getMemberDecl() && isa<CXXThisExpr>(Base)) {
unsigned diag = VD->getType()->isReferenceType()
? diag::warn_reference_field_is_uninit
: diag::warn_field_is_uninit;
- S.Diag(ME->getExprLoc(), diag) << ME->getMemberNameInfo().getName();
- return;
+ S.Diag(FieldME->getExprLoc(), diag) << VD;
}
+ return;
}
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
@@ -1909,11 +1985,7 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc,
}
ExprResult Init = InitExpr;
- if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent() &&
- !FD->getDeclContext()->isDependentContext()) {
- // Note: We don't type-check when we're in a dependent context, because
- // the initialization-substitution code does not properly handle direct
- // list initialization. We have the same hackaround for ctor-initializers.
+ if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) {
Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list)
<< /*at end of ctor*/1 << InitExpr->getSourceRange();
@@ -1930,14 +2002,12 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc,
FD->setInvalidDecl();
return;
}
-
- CheckImplicitConversions(Init.get(), InitLoc);
}
- // C++0x [class.base.init]p7:
+ // C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- Init = MaybeCreateExprWithCleanups(Init);
+ Init = ActOnFinishFullExpr(Init.take(), InitLoc);
if (Init.isInvalid()) {
FD->setInvalidDecl();
return;
@@ -2096,10 +2166,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
// Look for a member, first.
DeclContext::lookup_result Result
= ClassDecl->lookup(MemberOrBase);
- if (Result.first != Result.second) {
+ if (!Result.empty()) {
ValueDecl *Member;
- if ((Member = dyn_cast<FieldDecl>(*Result.first)) ||
- (Member = dyn_cast<IndirectFieldDecl>(*Result.first))) {
+ if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
+ (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) {
if (EllipsisLoc.isValid())
Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
<< MemberOrBase
@@ -2295,10 +2365,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
Args = ParenList->getExprs();
NumArgs = ParenList->getNumExprs();
- } else {
- InitListExpr *InitList = cast<InitListExpr>(Init);
+ } else if (InitListExpr *InitList = dyn_cast<InitListExpr>(Init)) {
Args = InitList->getInits();
NumArgs = InitList->getNumInits();
+ } else {
+ // Template instantiation doesn't reconstruct ParenListExprs for us.
+ Args = &Init;
+ NumArgs = 1;
}
if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, IdLoc)
@@ -2349,29 +2422,15 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (MemberInit.isInvalid())
return true;
- CheckImplicitConversions(MemberInit.get(),
- InitRange.getBegin());
-
- // C++0x [class.base.init]p7:
+ // C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- MemberInit = MaybeCreateExprWithCleanups(MemberInit);
+ MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin());
if (MemberInit.isInvalid())
return true;
- // If we are in a dependent context, template instantiation will
- // perform this type-checking again. Just save the arguments that we
- // received.
- // FIXME: This isn't quite ideal, since our ASTs don't capture all
- // of the information that we have about the member
- // initializer. However, deconstructing the ASTs is a dicey process,
- // and this approach is far more likely to get the corner cases right.
- if (CurContext->isDependentContext()) {
- // The existing Init will do fine.
- } else {
- Init = MemberInit.get();
- CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc);
- }
+ Init = MemberInit.get();
+ CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc);
}
if (DirectMember) {
@@ -2389,7 +2448,7 @@ MemInitResult
Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
CXXRecordDecl *ClassDecl) {
SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
- if (!LangOpts.CPlusPlus0x)
+ if (!LangOpts.CPlusPlus11)
return Diag(NameLoc, diag::err_delegating_ctor)
<< TInfo->getTypeLoc().getLocalSourceRange();
Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor);
@@ -2421,12 +2480,11 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() &&
"Delegating constructor with no target?");
- CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin());
-
- // C++0x [class.base.init]p7:
+ // C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- DelegationInit = MaybeCreateExprWithCleanups(DelegationInit);
+ DelegationInit = ActOnFinishFullExpr(DelegationInit.get(),
+ InitRange.getBegin());
if (DelegationInit.isInvalid())
return true;
@@ -2555,12 +2613,10 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
if (BaseInit.isInvalid())
return true;
- CheckImplicitConversions(BaseInit.get(), InitRange.getBegin());
-
- // C++0x [class.base.init]p7:
- // The initialization of each base and member constitutes a
+ // C++11 [class.base.init]p7:
+ // The initialization of each base and member constitutes a
// full-expression.
- BaseInit = MaybeCreateExprWithCleanups(BaseInit);
+ BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin());
if (BaseInit.isInvalid())
return true;
@@ -2582,9 +2638,10 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
}
// Create a static_cast\<T&&>(expr).
-static Expr *CastForMoving(Sema &SemaRef, Expr *E) {
- QualType ExprType = E->getType();
- QualType TargetType = SemaRef.Context.getRValueReferenceType(ExprType);
+static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) {
+ if (T.isNull()) T = E->getType();
+ QualType TargetType = SemaRef.BuildReferenceType(
+ T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName());
SourceLocation ExprLoc = E->getLocStart();
TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo(
TargetType, ExprLoc);
@@ -2599,7 +2656,8 @@ static Expr *CastForMoving(Sema &SemaRef, Expr *E) {
enum ImplicitInitializerKind {
IIK_Default,
IIK_Copy,
- IIK_Move
+ IIK_Move,
+ IIK_Inherit
};
static bool
@@ -2615,6 +2673,35 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
ExprResult BaseInit;
switch (ImplicitInitKind) {
+ case IIK_Inherit: {
+ const CXXRecordDecl *Inherited =
+ Constructor->getInheritedConstructor()->getParent();
+ const CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl();
+ if (Base && Inherited->getCanonicalDecl() == Base->getCanonicalDecl()) {
+ // C++11 [class.inhctor]p8:
+ // Each expression in the expression-list is of the form
+ // static_cast<T&&>(p), where p is the name of the corresponding
+ // constructor parameter and T is the declared type of p.
+ SmallVector<Expr*, 16> Args;
+ for (unsigned I = 0, E = Constructor->getNumParams(); I != E; ++I) {
+ ParmVarDecl *PD = Constructor->getParamDecl(I);
+ ExprResult ArgExpr =
+ SemaRef.BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
+ VK_LValue, SourceLocation());
+ if (ArgExpr.isInvalid())
+ return true;
+ Args.push_back(CastForMoving(SemaRef, ArgExpr.take(), PD->getType()));
+ }
+
+ InitializationKind InitKind = InitializationKind::CreateDirect(
+ Constructor->getLocation(), SourceLocation(), SourceLocation());
+ InitializationSequence InitSeq(SemaRef, InitEntity, InitKind,
+ Args.data(), Args.size());
+ BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, Args);
+ break;
+ }
+ }
+ // Fall through.
case IIK_Default: {
InitializationKind InitKind
= InitializationKind::CreateDefault(Constructor->getLocation());
@@ -2765,7 +2852,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
= VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc,
IterationVarName, SizeType,
SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None, SC_None);
+ SC_None);
IndexVariables.push_back(IterationVar);
// Create a reference to the iteration variable.
@@ -2837,7 +2924,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
return false;
}
- assert(ImplicitInitKind == IIK_Default && "Unhandled implicit init kind!");
+ assert((ImplicitInitKind == IIK_Default || ImplicitInitKind == IIK_Inherit) &&
+ "Unhandled implicit init kind!");
QualType FieldBaseElementType =
SemaRef.Context.getBaseElementType(Field->getType());
@@ -2928,6 +3016,8 @@ struct BaseAndFieldInfo {
IIK = IIK_Copy;
else if (Generated && Ctor->isMoveConstructor())
IIK = IIK_Move;
+ else if (Ctor->getInheritedConstructor())
+ IIK = IIK_Inherit;
else
IIK = IIK_Default;
}
@@ -2939,6 +3029,7 @@ struct BaseAndFieldInfo {
return true;
case IIK_Default:
+ case IIK_Inherit:
return false;
}
@@ -3059,19 +3150,17 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
return false;
}
-bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
- CXXCtorInitializer **Initializers,
- unsigned NumInitializers,
- bool AnyErrors) {
+bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
+ ArrayRef<CXXCtorInitializer *> Initializers) {
if (Constructor->isDependentContext()) {
// Just store the initializers as written, they will be checked during
// instantiation.
- if (NumInitializers > 0) {
- Constructor->setNumCtorInitializers(NumInitializers);
+ if (!Initializers.empty()) {
+ Constructor->setNumCtorInitializers(Initializers.size());
CXXCtorInitializer **baseOrMemberInitializers =
- new (Context) CXXCtorInitializer*[NumInitializers];
- memcpy(baseOrMemberInitializers, Initializers,
- NumInitializers * sizeof(CXXCtorInitializer*));
+ new (Context) CXXCtorInitializer*[Initializers.size()];
+ memcpy(baseOrMemberInitializers, Initializers.data(),
+ Initializers.size() * sizeof(CXXCtorInitializer*));
Constructor->setCtorInitializers(baseOrMemberInitializers);
}
@@ -3092,7 +3181,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
bool HadError = false;
- for (unsigned i = 0; i < NumInitializers; i++) {
+ for (unsigned i = 0; i < Initializers.size(); i++) {
CXXCtorInitializer *Member = Initializers[i];
if (Member->isBaseInitializer())
@@ -3168,7 +3257,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
// If we're not generating the implicit copy/move constructor, then we'll
// handle anonymous struct/union fields based on their individual
// indirect fields.
- if (F->isAnonymousStructOrUnion() && Info.IIK == IIK_Default)
+ if (F->isAnonymousStructOrUnion() && !Info.isImplicitCopyOrMove())
continue;
if (CollectFieldInitializer(*this, Info, F))
@@ -3177,7 +3266,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
}
// Beyond this point, we only consider default initialization.
- if (Info.IIK != IIK_Default)
+ if (Info.isImplicitCopyOrMove())
continue;
if (IndirectFieldDecl *F = dyn_cast<IndirectFieldDecl>(*Mem)) {
@@ -3195,7 +3284,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
}
}
- NumInitializers = Info.AllToInit.size();
+ unsigned NumInitializers = Info.AllToInit.size();
if (NumInitializers > 0) {
Constructor->setNumCtorInitializers(NumInitializers);
CXXCtorInitializer **baseOrMemberInitializers =
@@ -3213,13 +3302,17 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
return HadError;
}
-static void *GetKeyForTopLevelField(FieldDecl *Field) {
- // For anonymous unions, use the class declaration as the key.
+static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) {
if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
- if (RT->getDecl()->isAnonymousStructOrUnion())
- return static_cast<void *>(RT->getDecl());
+ const RecordDecl *RD = RT->getDecl();
+ if (RD->isAnonymousStructOrUnion()) {
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ E = RD->field_end(); Field != E; ++Field)
+ PopulateKeysForFields(*Field, IdealInits);
+ return;
+ }
}
- return static_cast<void *>(Field);
+ IdealInits.push_back(Field);
}
static void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
@@ -3231,40 +3324,19 @@ static void *GetKeyForMember(ASTContext &Context,
if (!Member->isAnyMemberInitializer())
return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
- // For fields injected into the class via declaration of an anonymous union,
- // use its anonymous union class declaration as the unique key.
- FieldDecl *Field = Member->getAnyMember();
-
- // If the field is a member of an anonymous struct or union, our key
- // is the anonymous record decl that's a direct child of the class.
- RecordDecl *RD = Field->getParent();
- if (RD->isAnonymousStructOrUnion()) {
- while (true) {
- RecordDecl *Parent = cast<RecordDecl>(RD->getDeclContext());
- if (Parent->isAnonymousStructOrUnion())
- RD = Parent;
- else
- break;
- }
-
- return static_cast<void *>(RD);
- }
-
- return static_cast<void *>(Field);
+ return Member->getAnyMember();
}
-static void
-DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
- const CXXConstructorDecl *Constructor,
- CXXCtorInitializer **Inits,
- unsigned NumInits) {
+static void DiagnoseBaseOrMemInitializerOrder(
+ Sema &SemaRef, const CXXConstructorDecl *Constructor,
+ ArrayRef<CXXCtorInitializer *> Inits) {
if (Constructor->getDeclContext()->isDependentContext())
return;
// Don't check initializers order unless the warning is enabled at the
// location of at least one initializer.
bool ShouldCheckOrder = false;
- for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) {
+ for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order,
Init->getSourceLocation())
@@ -3303,14 +3375,14 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
if (Field->isUnnamedBitfield())
continue;
- IdealInitKeys.push_back(GetKeyForTopLevelField(*Field));
+ PopulateKeysForFields(*Field, IdealInitKeys);
}
unsigned NumIdealInits = IdealInitKeys.size();
unsigned IdealIndex = 0;
CXXCtorInitializer *PrevInit = 0;
- for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) {
+ for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
void *InitKey = GetKeyForMember(SemaRef.Context, Init);
@@ -3360,7 +3432,7 @@ bool CheckRedundantInit(Sema &S,
return false;
}
- if (FieldDecl *Field = Init->getMember())
+ if (FieldDecl *Field = Init->getAnyMember())
S.Diag(Init->getSourceLocation(),
diag::err_multiple_mem_initialization)
<< Field->getDeclName()
@@ -3420,8 +3492,7 @@ bool CheckRedundantUnionInit(Sema &S,
/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
SourceLocation ColonLoc,
- CXXCtorInitializer **meminits,
- unsigned NumMemInits,
+ ArrayRef<CXXCtorInitializer*> MemInits,
bool AnyErrors) {
if (!ConstructorDecl)
return;
@@ -3436,9 +3507,6 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
return;
}
- CXXCtorInitializer **MemInits =
- reinterpret_cast<CXXCtorInitializer **>(meminits);
-
// Mapping for the duplicate initializers check.
// For member initializers, this is keyed with a FieldDecl*.
// For base initializers, this is keyed with a Type*.
@@ -3448,7 +3516,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
RedundantUnionMap MemberUnions;
bool HadError = false;
- for (unsigned i = 0; i < NumMemInits; i++) {
+ for (unsigned i = 0; i < MemInits.size(); i++) {
CXXCtorInitializer *Init = MemInits[i];
// Set the source order index.
@@ -3466,7 +3534,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
} else {
assert(Init->isDelegatingInitializer());
// This must be the only initializer
- if (NumMemInits != 1) {
+ if (MemInits.size() != 1) {
Diag(Init->getSourceLocation(),
diag::err_delegating_initializer_alone)
<< Init->getSourceRange() << MemInits[i ? 0 : 1]->getSourceRange();
@@ -3481,9 +3549,9 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
if (HadError)
return;
- DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits, NumMemInits);
+ DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits);
- SetCtorInitializers(Constructor, MemInits, NumMemInits, AnyErrors);
+ SetCtorInitializers(Constructor, AnyErrors, MemInits);
}
void
@@ -3605,7 +3673,7 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(CDtorDecl))
- SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false);
+ SetCtorInitializers(Constructor, /*AnyErrors=*/false);
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
@@ -3748,7 +3816,7 @@ struct CheckAbstractUsage {
switch (TL.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- case TypeLoc::CLASS: Check(cast<CLASS##TypeLoc>(TL), Sel); break;
+ case TypeLoc::CLASS: Check(TL.castAs<CLASS##TypeLoc>(), Sel); break;
#include "clang/AST/TypeLocNodes.def"
}
}
@@ -3933,9 +4001,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// C++ [class.mem]p14:
// In addition, if class T has a user-declared constructor (12.1), every
// non-static data member of class T shall have a name different from T.
- for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
- R.first != R.second; ++R.first) {
- NamedDecl *D = *R.first;
+ DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
+ for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
+ ++I) {
+ NamedDecl *D = *I;
if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) ||
isa<IndirectFieldDecl>(D)) {
Diag(D->getLocation(), diag::err_member_name_of_class)
@@ -3958,18 +4027,34 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
DiagnoseAbstractType(Record);
}
- // See if a method overloads virtual methods in a base
- /// class without overriding any.
if (!Record->isDependentType()) {
for (CXXRecordDecl::method_iterator M = Record->method_begin(),
MEnd = Record->method_end();
M != MEnd; ++M) {
+ // See if a method overloads virtual methods in a base
+ // class without overriding any.
if (!M->isStatic())
DiagnoseHiddenVirtualMethods(Record, *M);
+
+ // Check whether the explicitly-defaulted special members are valid.
+ if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
+ CheckExplicitlyDefaultedSpecialMember(*M);
+
+ // For an explicitly defaulted or deleted special member, we defer
+ // determining triviality until the class is complete. That time is now!
+ if (!M->isImplicit() && !M->isUserProvided()) {
+ CXXSpecialMember CSM = getSpecialMember(*M);
+ if (CSM != CXXInvalid) {
+ M->setTrivial(SpecialMemberIsTrivial(*M, CSM));
+
+ // Inform the class that we've finished declaring this member.
+ Record->finishedDefaultedOrDeletedMember(*M);
+ }
+ }
}
}
- // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member
+ // C++11 [dcl.constexpr]p8: A constexpr specifier for a non-static member
// function that is not a constructor declares that member function to be
// const. [...] The class of which that function is a member shall be
// a literal type.
@@ -3977,7 +4062,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// If the class has virtual bases, any constexpr members will already have
// been diagnosed by the checks performed on the member declaration, so
// suppress this (less useful) diagnostic.
- if (LangOpts.CPlusPlus0x && !Record->isDependentType() &&
+ //
+ // We delay this until we know whether an explicitly-defaulted (or deleted)
+ // destructor for the class is trivial.
+ if (LangOpts.CPlusPlus11 && !Record->isDependentType() &&
!Record->isLiteral() && !Record->getNumVBases()) {
for (CXXRecordDecl::method_iterator M = Record->method_begin(),
MEnd = Record->method_end();
@@ -4005,22 +4093,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
- // Declare inherited constructors. We do this eagerly here because:
- // - The standard requires an eager diagnostic for conflicting inherited
+ // Declare inheriting constructors. We do this eagerly here because:
+ // - The standard requires an eager diagnostic for conflicting inheriting
// constructors from different classes.
// - The lazy declaration of the other implicit constructors is so as to not
// waste space and performance on classes that are not meant to be
// instantiated (e.g. meta-functions). This doesn't apply to classes that
- // have inherited constructors.
- DeclareInheritedConstructors(Record);
-}
-
-void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) {
- for (CXXRecordDecl::method_iterator MI = Record->method_begin(),
- ME = Record->method_end();
- MI != ME; ++MI)
- if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted())
- CheckExplicitlyDefaultedSpecialMember(*MI);
+ // have inheriting constructors.
+ DeclareInheritingConstructors(Record);
}
/// Is the special member function which would be selected to perform the
@@ -4043,7 +4123,7 @@ static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
Sema::CXXSpecialMember CSM,
bool ConstArg) {
- if (!S.getLangOpts().CPlusPlus0x)
+ if (!S.getLangOpts().CPlusPlus11)
return false;
// C++11 [dcl.constexpr]p4:
@@ -4136,7 +4216,9 @@ computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) {
case Sema::CXXInvalid:
break;
}
- llvm_unreachable("only special members have implicit exception specs");
+ assert(cast<CXXConstructorDecl>(MD)->getInheritedConstructor() &&
+ "only special members have implicit exception specs");
+ return S.ComputeInheritingCtorExceptionSpec(cast<CXXConstructorDecl>(MD));
}
static void
@@ -4145,8 +4227,7 @@ updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT,
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
ExceptSpec.getEPI(EPI);
const FunctionProtoType *NewFPT = cast<FunctionProtoType>(
- S.Context.getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
- FPT->getNumArgs(), EPI));
+ S.Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(), EPI));
FD->setType(QualType(NewFPT, 0));
}
@@ -4172,9 +4253,6 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD)
CanonicalFPT, ExceptSpec);
}
-static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl *ClassDecl);
-static bool isImplicitCopyAssignmentArgConst(Sema &S, CXXRecordDecl *ClassDecl);
-
void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
CXXRecordDecl *RD = MD->getParent();
CXXSpecialMember CSM = getSpecialMember(MD);
@@ -4205,37 +4283,19 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
Diag(MD->getLocation(), diag::err_defaulted_special_member_params)
<< CSM << MD->getSourceRange();
HadError = true;
+ } else if (MD->isVariadic()) {
+ Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic)
+ << CSM << MD->getSourceRange();
+ HadError = true;
}
const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>();
- // Compute argument constness, constexpr, and triviality.
bool CanHaveConstParam = false;
- bool Trivial = false;
- switch (CSM) {
- case CXXDefaultConstructor:
- Trivial = RD->hasTrivialDefaultConstructor();
- break;
- case CXXCopyConstructor:
- CanHaveConstParam = isImplicitCopyCtorArgConst(*this, RD);
- Trivial = RD->hasTrivialCopyConstructor();
- break;
- case CXXCopyAssignment:
- CanHaveConstParam = isImplicitCopyAssignmentArgConst(*this, RD);
- Trivial = RD->hasTrivialCopyAssignment();
- break;
- case CXXMoveConstructor:
- Trivial = RD->hasTrivialMoveConstructor();
- break;
- case CXXMoveAssignment:
- Trivial = RD->hasTrivialMoveAssignment();
- break;
- case CXXDestructor:
- Trivial = RD->hasTrivialDestructor();
- break;
- case CXXInvalid:
- llvm_unreachable("non-special member explicitly defaulted!");
- }
+ if (CSM == CXXCopyConstructor)
+ CanHaveConstParam = RD->implicitCopyConstructorHasConstParam();
+ else if (CSM == CXXCopyAssignment)
+ CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam();
QualType ReturnType = Context.VoidTy;
if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) {
@@ -4284,14 +4344,6 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
}
HadError = true;
}
-
- // If a function is explicitly defaulted on its first declaration, it shall
- // have the same parameter type as if it had been implicitly declared.
- // (Presumably this is to prevent it from being trivial?)
- if (!HasConstParam && CanHaveConstParam && First)
- Diag(MD->getLocation(),
- diag::err_defaulted_special_member_copy_non_const_param)
- << (CSM == CXXCopyAssignment);
} else if (ExpectedParams) {
// A copy assignment operator can take its argument by value, but a
// defaulted one cannot.
@@ -4300,16 +4352,6 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
HadError = true;
}
- // Rebuild the type with the implicit exception specification added, if we
- // are going to need it.
- const FunctionProtoType *ImplicitType = 0;
- if (First || Type->hasExceptionSpec()) {
- FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
- computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI);
- ImplicitType = cast<FunctionProtoType>(
- Context.getFunctionType(ReturnType, &ArgType, ExpectedParams, EPI));
- }
-
// C++11 [dcl.fct.def.default]p2:
// An explicitly-defaulted function may be declared constexpr only if it
// would have been implicitly declared as constexpr,
@@ -4324,13 +4366,23 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// FIXME: Explain why the constructor can't be constexpr.
HadError = true;
}
+
// and may have an explicit exception-specification only if it is compatible
// with the exception-specification on the implicit declaration.
- if (Type->hasExceptionSpec() &&
- CheckEquivalentExceptionSpec(
- PDiag(diag::err_incorrect_defaulted_exception_spec) << CSM,
- PDiag(), ImplicitType, SourceLocation(), Type, MD->getLocation()))
- HadError = true;
+ if (Type->hasExceptionSpec()) {
+ // Delay the check if this is the first declaration of the special member,
+ // since we may not have parsed some necessary in-class initializers yet.
+ if (First) {
+ // If the exception specification needs to be instantiated, do so now,
+ // before we clobber it with an EST_Unevaluated specification below.
+ if (Type->getExceptionSpecType() == EST_Uninstantiated) {
+ InstantiateExceptionSpec(MD->getLocStart(), MD);
+ Type = MD->getType()->getAs<FunctionProtoType>();
+ }
+ DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type));
+ } else
+ CheckExplicitlyDefaultedMemberExceptionSpec(MD, Type);
+ }
// If a function is explicitly defaulted on its first declaration,
if (First) {
@@ -4340,16 +4392,18 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// -- it is implicitly considered to have the same exception-specification
// as if it had been implicitly declared,
- MD->setType(QualType(ImplicitType, 0));
-
- // Such a function is also trivial if the implicitly-declared function
- // would have been.
- MD->setTrivial(Trivial);
+ FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
+ EPI.ExceptionSpecType = EST_Unevaluated;
+ EPI.ExceptionSpecDecl = MD;
+ MD->setType(Context.getFunctionType(ReturnType,
+ ArrayRef<QualType>(&ArgType,
+ ExpectedParams),
+ EPI));
}
if (ShouldDeleteSpecialMember(MD, CSM)) {
if (First) {
- MD->setDeletedAsWritten();
+ SetDeclDeleted(MD, MD->getLocation());
} else {
// C++11 [dcl.fct.def.default]p4:
// [For a] user-provided explicitly-defaulted function [...] if such a
@@ -4363,6 +4417,36 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
MD->setInvalidDecl();
}
+/// Check whether the exception specification provided for an
+/// explicitly-defaulted special member matches the exception specification
+/// that would have been generated for an implicit special member, per
+/// C++11 [dcl.fct.def.default]p2.
+void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
+ CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) {
+ // Compute the implicit exception specification.
+ FunctionProtoType::ExtProtoInfo EPI;
+ computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI);
+ const FunctionProtoType *ImplicitType = cast<FunctionProtoType>(
+ Context.getFunctionType(Context.VoidTy, ArrayRef<QualType>(), EPI));
+
+ // Ensure that it matches.
+ CheckEquivalentExceptionSpec(
+ PDiag(diag::err_incorrect_defaulted_exception_spec)
+ << getSpecialMember(MD), PDiag(),
+ ImplicitType, SourceLocation(),
+ SpecifiedType, MD->getLocation());
+}
+
+void Sema::CheckDelayedExplicitlyDefaultedMemberExceptionSpecs() {
+ for (unsigned I = 0, N = DelayedDefaultedMemberExceptionSpecs.size();
+ I != N; ++I)
+ CheckExplicitlyDefaultedMemberExceptionSpec(
+ DelayedDefaultedMemberExceptionSpecs[I].first,
+ DelayedDefaultedMemberExceptionSpecs[I].second);
+
+ DelayedDefaultedMemberExceptionSpecs.clear();
+}
+
namespace {
struct SpecialMemberDeletionInfo {
Sema &S;
@@ -4688,7 +4772,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
return false;
CXXRecordDecl *RD = MD->getParent();
assert(!RD->isDependentType() && "do deletion after instantiation");
- if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl())
+ if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl())
return false;
// C++11 [expr.lambda.prim]p19:
@@ -4722,12 +4806,28 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
if (RD->hasUserDeclaredMoveConstructor() &&
(!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) {
if (!Diagnose) return true;
- UserDeclaredMove = RD->getMoveConstructor();
+
+ // Find any user-declared move constructor.
+ for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
+ E = RD->ctor_end(); I != E; ++I) {
+ if (I->isMoveConstructor()) {
+ UserDeclaredMove = *I;
+ break;
+ }
+ }
assert(UserDeclaredMove);
} else if (RD->hasUserDeclaredMoveAssignment() &&
(!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) {
if (!Diagnose) return true;
- UserDeclaredMove = RD->getMoveAssignmentOperator();
+
+ // Find any user-declared move assignment operator.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ if (I->isMoveAssignmentOperator()) {
+ UserDeclaredMove = *I;
+ break;
+ }
+ }
assert(UserDeclaredMove);
}
@@ -4783,6 +4883,422 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
return false;
}
+/// Perform lookup for a special member of the specified kind, and determine
+/// whether it is trivial. If the triviality can be determined without the
+/// lookup, skip it. This is intended for use when determining whether a
+/// special member of a containing object is trivial, and thus does not ever
+/// perform overload resolution for default constructors.
+///
+/// If \p Selected is not \c NULL, \c *Selected will be filled in with the
+/// member that was most likely to be intended to be trivial, if any.
+static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
+ Sema::CXXSpecialMember CSM, unsigned Quals,
+ CXXMethodDecl **Selected) {
+ if (Selected)
+ *Selected = 0;
+
+ switch (CSM) {
+ case Sema::CXXInvalid:
+ llvm_unreachable("not a special member");
+
+ case Sema::CXXDefaultConstructor:
+ // C++11 [class.ctor]p5:
+ // A default constructor is trivial if:
+ // - all the [direct subobjects] have trivial default constructors
+ //
+ // Note, no overload resolution is performed in this case.
+ if (RD->hasTrivialDefaultConstructor())
+ return true;
+
+ if (Selected) {
+ // If there's a default constructor which could have been trivial, dig it
+ // out. Otherwise, if there's any user-provided default constructor, point
+ // to that as an example of why there's not a trivial one.
+ CXXConstructorDecl *DefCtor = 0;
+ if (RD->needsImplicitDefaultConstructor())
+ S.DeclareImplicitDefaultConstructor(RD);
+ for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(),
+ CE = RD->ctor_end(); CI != CE; ++CI) {
+ if (!CI->isDefaultConstructor())
+ continue;
+ DefCtor = *CI;
+ if (!DefCtor->isUserProvided())
+ break;
+ }
+
+ *Selected = DefCtor;
+ }
+
+ return false;
+
+ case Sema::CXXDestructor:
+ // C++11 [class.dtor]p5:
+ // A destructor is trivial if:
+ // - all the direct [subobjects] have trivial destructors
+ if (RD->hasTrivialDestructor())
+ return true;
+
+ if (Selected) {
+ if (RD->needsImplicitDestructor())
+ S.DeclareImplicitDestructor(RD);
+ *Selected = RD->getDestructor();
+ }
+
+ return false;
+
+ case Sema::CXXCopyConstructor:
+ // C++11 [class.copy]p12:
+ // A copy constructor is trivial if:
+ // - the constructor selected to copy each direct [subobject] is trivial
+ if (RD->hasTrivialCopyConstructor()) {
+ if (Quals == Qualifiers::Const)
+ // We must either select the trivial copy constructor or reach an
+ // ambiguity; no need to actually perform overload resolution.
+ return true;
+ } else if (!Selected) {
+ return false;
+ }
+ // In C++98, we are not supposed to perform overload resolution here, but we
+ // treat that as a language defect, as suggested on cxx-abi-dev, to treat
+ // cases like B as having a non-trivial copy constructor:
+ // struct A { template<typename T> A(T&); };
+ // struct B { mutable A a; };
+ goto NeedOverloadResolution;
+
+ case Sema::CXXCopyAssignment:
+ // C++11 [class.copy]p25:
+ // A copy assignment operator is trivial if:
+ // - the assignment operator selected to copy each direct [subobject] is
+ // trivial
+ if (RD->hasTrivialCopyAssignment()) {
+ if (Quals == Qualifiers::Const)
+ return true;
+ } else if (!Selected) {
+ return false;
+ }
+ // In C++98, we are not supposed to perform overload resolution here, but we
+ // treat that as a language defect.
+ goto NeedOverloadResolution;
+
+ case Sema::CXXMoveConstructor:
+ case Sema::CXXMoveAssignment:
+ NeedOverloadResolution:
+ Sema::SpecialMemberOverloadResult *SMOR =
+ S.LookupSpecialMember(RD, CSM,
+ Quals & Qualifiers::Const,
+ Quals & Qualifiers::Volatile,
+ /*RValueThis*/false, /*ConstThis*/false,
+ /*VolatileThis*/false);
+
+ // The standard doesn't describe how to behave if the lookup is ambiguous.
+ // We treat it as not making the member non-trivial, just like the standard
+ // mandates for the default constructor. This should rarely matter, because
+ // the member will also be deleted.
+ if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+ return true;
+
+ if (!SMOR->getMethod()) {
+ assert(SMOR->getKind() ==
+ Sema::SpecialMemberOverloadResult::NoMemberOrDeleted);
+ return false;
+ }
+
+ // We deliberately don't check if we found a deleted special member. We're
+ // not supposed to!
+ if (Selected)
+ *Selected = SMOR->getMethod();
+ return SMOR->getMethod()->isTrivial();
+ }
+
+ llvm_unreachable("unknown special method kind");
+}
+
+static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) {
+ for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(), CE = RD->ctor_end();
+ CI != CE; ++CI)
+ if (!CI->isImplicit())
+ return *CI;
+
+ // Look for constructor templates.
+ typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> tmpl_iter;
+ for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); TI != TE; ++TI) {
+ if (CXXConstructorDecl *CD =
+ dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl()))
+ return CD;
+ }
+
+ return 0;
+}
+
+/// The kind of subobject we are checking for triviality. The values of this
+/// enumeration are used in diagnostics.
+enum TrivialSubobjectKind {
+ /// The subobject is a base class.
+ TSK_BaseClass,
+ /// The subobject is a non-static data member.
+ TSK_Field,
+ /// The object is actually the complete object.
+ TSK_CompleteObject
+};
+
+/// Check whether the special member selected for a given type would be trivial.
+static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
+ QualType SubType,
+ Sema::CXXSpecialMember CSM,
+ TrivialSubobjectKind Kind,
+ bool Diagnose) {
+ CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl();
+ if (!SubRD)
+ return true;
+
+ CXXMethodDecl *Selected;
+ if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
+ Diagnose ? &Selected : 0))
+ return true;
+
+ if (Diagnose) {
+ if (!Selected && CSM == Sema::CXXDefaultConstructor) {
+ S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor)
+ << Kind << SubType.getUnqualifiedType();
+ if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD))
+ S.Diag(CD->getLocation(), diag::note_user_declared_ctor);
+ } else if (!Selected)
+ S.Diag(SubobjLoc, diag::note_nontrivial_no_copy)
+ << Kind << SubType.getUnqualifiedType() << CSM << SubType;
+ else if (Selected->isUserProvided()) {
+ if (Kind == TSK_CompleteObject)
+ S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided)
+ << Kind << SubType.getUnqualifiedType() << CSM;
+ else {
+ S.Diag(SubobjLoc, diag::note_nontrivial_user_provided)
+ << Kind << SubType.getUnqualifiedType() << CSM;
+ S.Diag(Selected->getLocation(), diag::note_declared_at);
+ }
+ } else {
+ if (Kind != TSK_CompleteObject)
+ S.Diag(SubobjLoc, diag::note_nontrivial_subobject)
+ << Kind << SubType.getUnqualifiedType() << CSM;
+
+ // Explain why the defaulted or deleted special member isn't trivial.
+ S.SpecialMemberIsTrivial(Selected, CSM, Diagnose);
+ }
+ }
+
+ return false;
+}
+
+/// Check whether the members of a class type allow a special member to be
+/// trivial.
+static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
+ Sema::CXXSpecialMember CSM,
+ bool ConstArg, bool Diagnose) {
+ for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
+ FE = RD->field_end(); FI != FE; ++FI) {
+ if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
+ continue;
+
+ QualType FieldType = S.Context.getBaseElementType(FI->getType());
+
+ // Pretend anonymous struct or union members are members of this class.
+ if (FI->isAnonymousStructOrUnion()) {
+ if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(),
+ CSM, ConstArg, Diagnose))
+ return false;
+ continue;
+ }
+
+ // C++11 [class.ctor]p5:
+ // A default constructor is trivial if [...]
+ // -- no non-static data member of its class has a
+ // brace-or-equal-initializer
+ if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) {
+ if (Diagnose)
+ S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << *FI;
+ return false;
+ }
+
+ // Objective C ARC 4.3.5:
+ // [...] nontrivally ownership-qualified types are [...] not trivially
+ // default constructible, copy constructible, move constructible, copy
+ // assignable, move assignable, or destructible [...]
+ if (S.getLangOpts().ObjCAutoRefCount &&
+ FieldType.hasNonTrivialObjCLifetime()) {
+ if (Diagnose)
+ S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership)
+ << RD << FieldType.getObjCLifetime();
+ return false;
+ }
+
+ if (ConstArg && !FI->isMutable())
+ FieldType.addConst();
+ if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, CSM,
+ TSK_Field, Diagnose))
+ return false;
+ }
+
+ return true;
+}
+
+/// Diagnose why the specified class does not have a trivial special member of
+/// the given kind.
+void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
+ QualType Ty = Context.getRecordType(RD);
+ if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)
+ Ty.addConst();
+
+ checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, CSM,
+ TSK_CompleteObject, /*Diagnose*/true);
+}
+
+/// Determine whether a defaulted or deleted special member function is trivial,
+/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12,
+/// C++11 [class.copy]p25, and C++11 [class.dtor]p5.
+bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
+ bool Diagnose) {
+ assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough");
+
+ CXXRecordDecl *RD = MD->getParent();
+
+ bool ConstArg = false;
+
+ // C++11 [class.copy]p12, p25:
+ // A [special member] is trivial if its declared parameter type is the same
+ // as if it had been implicitly declared [...]
+ switch (CSM) {
+ case CXXDefaultConstructor:
+ case CXXDestructor:
+ // Trivial default constructors and destructors cannot have parameters.
+ break;
+
+ case CXXCopyConstructor:
+ case CXXCopyAssignment: {
+ // Trivial copy operations always have const, non-volatile parameter types.
+ ConstArg = true;
+ const ParmVarDecl *Param0 = MD->getParamDecl(0);
+ const ReferenceType *RT = Param0->getType()->getAs<ReferenceType>();
+ if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) {
+ if (Diagnose)
+ Diag(Param0->getLocation(), diag::note_nontrivial_param_type)
+ << Param0->getSourceRange() << Param0->getType()
+ << Context.getLValueReferenceType(
+ Context.getRecordType(RD).withConst());
+ return false;
+ }
+ break;
+ }
+
+ case CXXMoveConstructor:
+ case CXXMoveAssignment: {
+ // Trivial move operations always have non-cv-qualified parameters.
+ const ParmVarDecl *Param0 = MD->getParamDecl(0);
+ const RValueReferenceType *RT =
+ Param0->getType()->getAs<RValueReferenceType>();
+ if (!RT || RT->getPointeeType().getCVRQualifiers()) {
+ if (Diagnose)
+ Diag(Param0->getLocation(), diag::note_nontrivial_param_type)
+ << Param0->getSourceRange() << Param0->getType()
+ << Context.getRValueReferenceType(Context.getRecordType(RD));
+ return false;
+ }
+ break;
+ }
+
+ case CXXInvalid:
+ llvm_unreachable("not a special member");
+ }
+
+ // FIXME: We require that the parameter-declaration-clause is equivalent to
+ // that of an implicit declaration, not just that the declared parameter type
+ // matches, in order to prevent absuridities like a function simultaneously
+ // being a trivial copy constructor and a non-trivial default constructor.
+ // This issue has not yet been assigned a core issue number.
+ if (MD->getMinRequiredArguments() < MD->getNumParams()) {
+ if (Diagnose)
+ Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(),
+ diag::note_nontrivial_default_arg)
+ << MD->getParamDecl(MD->getMinRequiredArguments())->getSourceRange();
+ return false;
+ }
+ if (MD->isVariadic()) {
+ if (Diagnose)
+ Diag(MD->getLocation(), diag::note_nontrivial_variadic);
+ return false;
+ }
+
+ // C++11 [class.ctor]p5, C++11 [class.dtor]p5:
+ // A copy/move [constructor or assignment operator] is trivial if
+ // -- the [member] selected to copy/move each direct base class subobject
+ // is trivial
+ //
+ // C++11 [class.copy]p12, C++11 [class.copy]p25:
+ // A [default constructor or destructor] is trivial if
+ // -- all the direct base classes have trivial [default constructors or
+ // destructors]
+ for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
+ BE = RD->bases_end(); BI != BE; ++BI)
+ if (!checkTrivialSubobjectCall(*this, BI->getLocStart(),
+ ConstArg ? BI->getType().withConst()
+ : BI->getType(),
+ CSM, TSK_BaseClass, Diagnose))
+ return false;
+
+ // C++11 [class.ctor]p5, C++11 [class.dtor]p5:
+ // A copy/move [constructor or assignment operator] for a class X is
+ // trivial if
+ // -- for each non-static data member of X that is of class type (or array
+ // thereof), the constructor selected to copy/move that member is
+ // trivial
+ //
+ // C++11 [class.copy]p12, C++11 [class.copy]p25:
+ // A [default constructor or destructor] is trivial if
+ // -- for all of the non-static data members of its class that are of class
+ // type (or array thereof), each such class has a trivial [default
+ // constructor or destructor]
+ if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose))
+ return false;
+
+ // C++11 [class.dtor]p5:
+ // A destructor is trivial if [...]
+ // -- the destructor is not virtual
+ if (CSM == CXXDestructor && MD->isVirtual()) {
+ if (Diagnose)
+ Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD;
+ return false;
+ }
+
+ // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
+ // A [special member] for class X is trivial if [...]
+ // -- class X has no virtual functions and no virtual base classes
+ if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) {
+ if (!Diagnose)
+ return false;
+
+ if (RD->getNumVBases()) {
+ // Check for virtual bases. We already know that the corresponding
+ // member in all bases is trivial, so vbases must all be direct.
+ CXXBaseSpecifier &BS = *RD->vbases_begin();
+ assert(BS.isVirtual());
+ Diag(BS.getLocStart(), diag::note_nontrivial_has_virtual) << RD << 1;
+ return false;
+ }
+
+ // Must have a virtual method.
+ for (CXXRecordDecl::method_iterator MI = RD->method_begin(),
+ ME = RD->method_end(); MI != ME; ++MI) {
+ if (MI->isVirtual()) {
+ SourceLocation MLoc = MI->getLocStart();
+ Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0;
+ return false;
+ }
+ }
+
+ llvm_unreachable("dynamic class with no vbases and no virtual functions");
+ }
+
+ // Looks like it's trivial!
+ return true;
+}
+
/// \brief Data used with FindHiddenVirtualMethod
namespace {
struct FindHiddenVirtualMethodData {
@@ -4823,9 +5339,9 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
bool foundSameNameMethod = false;
SmallVector<CXXMethodDecl *, 8> overloadedMethods;
for (Path.Decls = BaseRecord->lookup(Name);
- Path.Decls.first != Path.Decls.second;
- ++Path.Decls.first) {
- NamedDecl *D = *Path.Decls.first;
+ !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;
@@ -4877,10 +5393,10 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
// 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.
- for (DeclContext::lookup_result res = DC->lookup(MD->getDeclName());
- res.first != res.second; ++res.first) {
- NamedDecl *ND = *res.first;
- if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*res.first))
+ DeclContext::lookup_result R = DC->lookup(MD->getDeclName());
+ for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ NamedDecl *ND = *I;
+ if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I))
ND = shad->getTargetDecl();
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods);
@@ -4935,39 +5451,53 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
if (!ClassDecl->hasUserDeclaredConstructor())
++ASTContext::NumImplicitDefaultConstructors;
- if (!ClassDecl->hasUserDeclaredCopyConstructor())
+ if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
++ASTContext::NumImplicitCopyConstructors;
- if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveConstructor())
+ // If the properties or semantics of the copy constructor couldn't be
+ // determined while the class was being declared, force a declaration
+ // of it now.
+ if (ClassDecl->needsOverloadResolutionForCopyConstructor())
+ DeclareImplicitCopyConstructor(ClassDecl);
+ }
+
+ if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) {
++ASTContext::NumImplicitMoveConstructors;
+ if (ClassDecl->needsOverloadResolutionForMoveConstructor())
+ DeclareImplicitMoveConstructor(ClassDecl);
+ }
+
if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
++ASTContext::NumImplicitCopyAssignmentOperators;
-
- // If we have a dynamic class, then the copy assignment operator may be
+
+ // If we have a dynamic class, then the copy assignment operator may be
// virtual, so we have to declare it immediately. This ensures that, e.g.,
- // it shows up in the right place in the vtable and that we diagnose
- // problems with the implicit exception specification.
- if (ClassDecl->isDynamicClass())
+ // it shows up in the right place in the vtable and that we diagnose
+ // problems with the implicit exception specification.
+ if (ClassDecl->isDynamicClass() ||
+ ClassDecl->needsOverloadResolutionForCopyAssignment())
DeclareImplicitCopyAssignment(ClassDecl);
}
- if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveAssignment()) {
+ if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) {
++ASTContext::NumImplicitMoveAssignmentOperators;
// Likewise for the move assignment operator.
- if (ClassDecl->isDynamicClass())
+ if (ClassDecl->isDynamicClass() ||
+ ClassDecl->needsOverloadResolutionForMoveAssignment())
DeclareImplicitMoveAssignment(ClassDecl);
}
if (!ClassDecl->hasUserDeclaredDestructor()) {
++ASTContext::NumImplicitDestructors;
-
- // If we have a dynamic class, then the destructor may be virtual, so we
+
+ // If we have a dynamic class, then the destructor may be virtual, so we
// have to declare the destructor immediately. This ensures that, e.g., it
// shows up in the right place in the vtable and that we diagnose problems
// with the implicit exception specification.
- if (ClassDecl->isDynamicClass())
+ if (ClassDecl->isDynamicClass() ||
+ ClassDecl->needsOverloadResolutionForDestructor())
DeclareImplicitDestructor(ClassDecl);
}
}
@@ -5150,8 +5680,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
- return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
- Proto->getNumArgs(), EPI);
+ return Context.getFunctionType(Context.VoidTy, Proto->getArgTypes(), EPI);
}
/// CheckConstructor - Checks a fully-formed constructor for
@@ -5331,7 +5860,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
EPI.Variadic = false;
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
- return Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
+ return Context.getFunctionType(Context.VoidTy, ArrayRef<QualType>(), EPI);
}
/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
@@ -5412,12 +5941,13 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
// of the errors above fired) and with the conversion type as the
// return type.
if (D.isInvalidType())
- R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo());
+ R = Context.getFunctionType(ConvType, ArrayRef<QualType>(),
+ Proto->getExtProtoInfo());
// C++0x explicit conversion operators.
if (D.getDeclSpec().isExplicitSpecified())
Diag(D.getDeclSpec().getExplicitSpecLoc(),
- getLangOpts().CPlusPlus0x ?
+ getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_explicit_conversion_functions :
diag::ext_explicit_conversion_functions)
<< SourceRange(D.getDeclSpec().getExplicitSpecLoc());
@@ -5551,11 +6081,11 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag |
Decl::IDNS_Namespace;
NamedDecl *PrevDecl = 0;
- for (DeclContext::lookup_result R
- = CurContext->getRedeclContext()->lookup(II);
- R.first != R.second; ++R.first) {
- if ((*R.first)->getIdentifierNamespace() & IDNS) {
- PrevDecl = *R.first;
+ 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;
}
}
@@ -5978,7 +6508,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
}
- // FIXME: We ignore attributes for now.
+ if (UDir)
+ ProcessDeclAttributeList(S, UDir, AttrList);
+
return UDir;
}
@@ -6019,14 +6551,12 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
case UnqualifiedId::IK_ConstructorTemplateId:
// C++11 inheriting constructors.
Diag(Name.getLocStart(),
- getLangOpts().CPlusPlus0x ?
- // FIXME: Produce warn_cxx98_compat_using_decl_constructor
- // instead once inheriting constructors work.
- diag::err_using_decl_constructor_unsupported :
+ getLangOpts().CPlusPlus11 ?
+ diag::warn_cxx98_compat_using_decl_constructor :
diag::err_using_decl_constructor)
<< SS.getRange();
- if (getLangOpts().CPlusPlus0x) break;
+ if (getLangOpts().CPlusPlus11) break;
return 0;
@@ -6046,7 +6576,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
if (!TargetName)
return 0;
- // Warn about using declarations.
+ // Warn about access declarations.
// TODO: store that the declaration was written without 'using' and
// talk about access decls instead of using decls in the
// diagnostics.
@@ -6116,7 +6646,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
// specialization. The UsingShadowDecl in D<T> then points directly
// to A::foo, which will look well-formed when we instantiate.
// The right solution is to not collapse the shadow-decl chain.
- if (!getLangOpts().CPlusPlus0x && CurContext->isRecord()) {
+ if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) {
DeclContext *OrigDC = Orig->getDeclContext();
// Handle enums and anonymous structs.
@@ -6605,7 +7135,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext))
return true;
- if (getLangOpts().CPlusPlus0x) {
+ if (getLangOpts().CPlusPlus11) {
// C++0x [namespace.udecl]p3:
// In a using-declaration used as a member-declaration, the
// nested-name-specifier shall name a base class of the class
@@ -6694,6 +7224,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
MultiTemplateParamsArg TemplateParamLists,
SourceLocation UsingLoc,
UnqualifiedId &Name,
+ AttributeList *AttrList,
TypeResult Type) {
// Skip up to the relevant declaration scope.
while (S->getFlags() & Scope::TemplateParamScope)
@@ -6740,6 +7271,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
if (Invalid)
NewTD->setInvalidDecl();
+ ProcessDeclAttributeList(S, NewTD, AttrList);
+
CheckTypedefForVariablyModifiedType(S, NewTD);
Invalid |= NewTD->isInvalidDecl();
@@ -6969,6 +7502,43 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
return ExceptSpec;
}
+Sema::ImplicitExceptionSpecification
+Sema::ComputeInheritingCtorExceptionSpec(CXXMethodDecl *MD) {
+ ImplicitExceptionSpecification ExceptSpec(*this);
+ // FIXME: Compute the exception spec.
+ return ExceptSpec;
+}
+
+namespace {
+/// RAII object to register a special member as being currently declared.
+struct DeclaringSpecialMember {
+ Sema &S;
+ Sema::SpecialMemberDecl D;
+ bool WasAlreadyBeingDeclared;
+
+ DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM)
+ : S(S), D(RD, CSM) {
+ WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D);
+ if (WasAlreadyBeingDeclared)
+ // This almost never happens, but if it does, ensure that our cache
+ // doesn't contain a stale result.
+ S.SpecialMemberCache.clear();
+
+ // FIXME: Register a note to be produced if we encounter an error while
+ // declaring the special member.
+ }
+ ~DeclaringSpecialMember() {
+ if (!WasAlreadyBeingDeclared)
+ S.SpecialMembersBeingDeclared.erase(D);
+ }
+
+ /// \brief Are we already trying to declare this special member?
+ bool isAlreadyBeingDeclared() const {
+ return WasAlreadyBeingDeclared;
+ }
+};
+}
+
CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
CXXRecordDecl *ClassDecl) {
// C++ [class.ctor]p5:
@@ -6977,9 +7547,13 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
// user-declared constructor for class X, a default constructor is
// implicitly declared. An implicitly-declared default constructor
// is an inline public member of its class.
- assert(!ClassDecl->hasUserDeclaredConstructor() &&
+ assert(ClassDecl->needsImplicitDefaultConstructor() &&
"Should not build implicit default constructor!");
+ DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor);
+ if (DSM.isAlreadyBeingDeclared())
+ return 0;
+
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXDefaultConstructor,
false);
@@ -6998,24 +7572,29 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
DefaultCon->setAccess(AS_public);
DefaultCon->setDefaulted();
DefaultCon->setImplicit();
- DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
// Build an exception specification pointing back at this constructor.
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = DefaultCon;
- DefaultCon->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
+ DefaultCon->setType(Context.getFunctionType(Context.VoidTy,
+ ArrayRef<QualType>(),
+ EPI));
+
+ // We don't need to use SpecialMemberIsTrivial here; triviality for default
+ // constructors is easy to compute.
+ DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
+
+ if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor))
+ SetDeclDeleted(DefaultCon, ClassLoc);
// Note that we have declared this constructor.
++ASTContext::NumImplicitDefaultConstructorsDeclared;
-
+
if (Scope *S = getScopeForContext(ClassDecl))
PushOnScopeChains(DefaultCon, S, false);
ClassDecl->addDecl(DefaultCon);
- if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor))
- DefaultCon->setDeletedAsWritten();
-
return DefaultCon;
}
@@ -7031,7 +7610,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
SynthesizedFunctionScope Scope(*this, Constructor);
DiagnosticErrorTrap Trap(Diags);
- if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) ||
+ if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) ||
Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
@@ -7051,16 +7630,12 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
}
void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
- if (!D) return;
- AdjustDeclIfTemplate(D);
-
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D);
-
- if (!ClassDecl->isDependentType())
- CheckExplicitlyDefaultedMethods(ClassDecl);
+ // Check that any explicitly-defaulted methods have exception specifications
+ // compatible with their implicit exception specifications.
+ CheckDelayedExplicitlyDefaultedMemberExceptionSpecs();
}
-void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
+void Sema::DeclareInheritingConstructors(CXXRecordDecl *ClassDecl) {
// We start with an initial pass over the base classes to collect those that
// inherit constructors from. If there are none, we can forgo all further
// processing.
@@ -7075,6 +7650,8 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
// If we inherit constructors from anything that is dependent, just
// abort processing altogether. We'll get another chance for the
// instantiations.
+ // FIXME: We need to ensure that any call to a constructor of this class
+ // is considered instantiation-dependent in this case.
return;
}
BasesToInheritFrom.push_back(Base->castAs<RecordType>());
@@ -7083,18 +7660,19 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
if (BasesToInheritFrom.empty())
return;
+ // FIXME: Constructor templates.
+
// Now collect the constructors that we already have in the current class.
// Those take precedence over inherited constructors.
- // C++0x [class.inhctor]p3: [...] a constructor is implicitly declared [...]
+ // C++11 [class.inhctor]p3: [...] a constructor is implicitly declared [...]
// unless there is a user-declared constructor with the same signature in
// the class where the using-declaration appears.
llvm::SmallSet<const Type *, 8> ExistingConstructors;
for (CXXRecordDecl::ctor_iterator CtorIt = ClassDecl->ctor_begin(),
CtorE = ClassDecl->ctor_end();
- CtorIt != CtorE; ++CtorIt) {
+ CtorIt != CtorE; ++CtorIt)
ExistingConstructors.insert(
Context.getCanonicalType(CtorIt->getType()).getTypePtr());
- }
DeclarationName CreatedCtorName =
Context.DeclarationNames.getCXXConstructorName(
@@ -7126,62 +7704,71 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
SourceLocation UsingLoc = UD ? UD->getLocation() :
ClassDecl->getLocation();
- // C++0x [class.inhctor]p1: The candidate set of inherited constructors
- // from the class X named in the using-declaration consists of actual
- // constructors and notional constructors that result from the
- // transformation of defaulted parameters as follows:
- // - all non-template default constructors of X, and
+ // C++11 [class.inhctor]p1:
+ // The candidate set of inherited constructors from the class X named in
+ // the using-declaration consists of actual constructors and notional
+ // constructors that result from the transformation of defaulted
+ // parameters as follows:
+ // - all non-template constructors of X, and
// - for each non-template constructor of X that has at least one
// parameter with a default argument, the set of constructors that
// results from omitting any ellipsis parameter specification and
// successively omitting parameters with a default argument from the
- // end of the parameter-type-list.
+ // end of the parameter-type-list, and
+ // FIXME: ...also constructor templates.
CXXConstructorDecl *BaseCtor = *CtorIt;
bool CanBeCopyOrMove = BaseCtor->isCopyOrMoveConstructor();
const FunctionProtoType *BaseCtorType =
BaseCtor->getType()->getAs<FunctionProtoType>();
- for (unsigned params = BaseCtor->getMinRequiredArguments(),
- maxParams = BaseCtor->getNumParams();
- params <= maxParams; ++params) {
+ // Determine whether this would be a copy or move constructor for the
+ // derived class.
+ if (BaseCtorType->getNumArgs() >= 1 &&
+ BaseCtorType->getArgType(0)->isReferenceType() &&
+ Context.hasSameUnqualifiedType(
+ BaseCtorType->getArgType(0)->getPointeeType(),
+ Context.getTagDeclType(ClassDecl)))
+ CanBeCopyOrMove = true;
+
+ ArrayRef<QualType> ArgTypes(BaseCtorType->getArgTypes());
+ FunctionProtoType::ExtProtoInfo EPI = BaseCtorType->getExtProtoInfo();
+ // Core issue (no number yet): the ellipsis is always discarded.
+ if (EPI.Variadic) {
+ Diag(UsingLoc, diag::warn_using_decl_constructor_ellipsis);
+ Diag(BaseCtor->getLocation(),
+ diag::note_using_decl_constructor_ellipsis);
+ EPI.Variadic = false;
+ }
+
+ for (unsigned Params = BaseCtor->getMinRequiredArguments(),
+ MaxParams = BaseCtor->getNumParams();
+ Params <= MaxParams; ++Params) {
// Skip default constructors. They're never inherited.
- if (params == 0)
+ if (Params == 0)
continue;
- // Skip copy and move constructors for the same reason.
- if (CanBeCopyOrMove && params == 1)
+
+ // Skip copy and move constructors for both base and derived class
+ // for the same reason.
+ if (CanBeCopyOrMove && Params == 1)
continue;
// Build up a function type for this particular constructor.
- // FIXME: The working paper does not consider that the exception spec
- // for the inheriting constructor might be larger than that of the
- // source. This code doesn't yet, either. When it does, this code will
- // need to be delayed until after exception specifications and in-class
- // member initializers are attached.
- const Type *NewCtorType;
- if (params == maxParams)
- NewCtorType = BaseCtorType;
- else {
- SmallVector<QualType, 16> Args;
- for (unsigned i = 0; i < params; ++i) {
- Args.push_back(BaseCtorType->getArgType(i));
- }
- FunctionProtoType::ExtProtoInfo ExtInfo =
- BaseCtorType->getExtProtoInfo();
- ExtInfo.Variadic = false;
- NewCtorType = Context.getFunctionType(BaseCtorType->getResultType(),
- Args.data(), params, ExtInfo)
- .getTypePtr();
- }
+ QualType NewCtorType =
+ Context.getFunctionType(Context.VoidTy, ArgTypes.slice(0, Params),
+ EPI);
const Type *CanonicalNewCtorType =
- Context.getCanonicalType(NewCtorType);
+ Context.getCanonicalType(NewCtorType).getTypePtr();
- // Now that we have the type, first check if the class already has a
- // constructor with this signature.
+ // C++11 [class.inhctor]p3:
+ // ... a constructor is implicitly declared with the same constructor
+ // characteristics unless there is a user-declared constructor with
+ // the same signature in the class where the using-declaration appears
if (ExistingConstructors.count(CanonicalNewCtorType))
continue;
- // Then we check if we have already declared an inherited constructor
- // with this signature.
+ // C++11 [class.inhctor]p7:
+ // If two using-declarations declare inheriting constructors with the
+ // same signature, the program is ill-formed
std::pair<ConstructorToSourceMap::iterator, bool> result =
InheritedConstructors.insert(std::make_pair(
CanonicalNewCtorType,
@@ -7203,35 +7790,47 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
diag::note_using_decl_constructor_conflict_previous_ctor);
Diag(PrevCtor->getLocation(),
diag::note_using_decl_constructor_conflict_previous_using);
+ } else {
+ // Core issue (no number): if the same inheriting constructor is
+ // produced by multiple base class constructors from the same base
+ // class, the inheriting constructor is defined as deleted.
+ SetDeclDeleted(result.first->second.second, UsingLoc);
}
continue;
}
// OK, we're there, now add the constructor.
- // C++0x [class.inhctor]p8: [...] that would be performed by a
- // user-written inline constructor [...]
DeclarationNameInfo DNI(CreatedCtorName, UsingLoc);
CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create(
- Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0),
+ Context, ClassDecl, UsingLoc, DNI, NewCtorType,
/*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true,
- /*ImplicitlyDeclared=*/true,
- // FIXME: Due to a defect in the standard, we treat inherited
- // constructors as constexpr even if that makes them ill-formed.
- /*Constexpr=*/BaseCtor->isConstexpr());
+ /*ImplicitlyDeclared=*/true, /*Constexpr=*/BaseCtor->isConstexpr());
NewCtor->setAccess(BaseCtor->getAccess());
+ // Build an unevaluated exception specification for this constructor.
+ EPI.ExceptionSpecType = EST_Unevaluated;
+ EPI.ExceptionSpecDecl = NewCtor;
+ NewCtor->setType(Context.getFunctionType(Context.VoidTy,
+ ArgTypes.slice(0, Params),
+ EPI));
+
// Build up the parameter decls and add them.
SmallVector<ParmVarDecl *, 16> ParamDecls;
- for (unsigned i = 0; i < params; ++i) {
- ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor,
- UsingLoc, UsingLoc,
- /*IdentifierInfo=*/0,
- BaseCtorType->getArgType(i),
- /*TInfo=*/0, SC_None,
- SC_None, /*DefaultArg=*/0));
+ for (unsigned i = 0; i < Params; ++i) {
+ ParmVarDecl *PD = ParmVarDecl::Create(Context, NewCtor,
+ UsingLoc, UsingLoc,
+ /*IdentifierInfo=*/0,
+ BaseCtorType->getArgType(i),
+ /*TInfo=*/0, SC_None,
+ /*DefaultArg=*/0);
+ PD->setScopeInfo(0, i);
+ PD->setImplicit();
+ ParamDecls.push_back(PD);
}
NewCtor->setParams(ParamDecls);
NewCtor->setInheritedConstructor(BaseCtor);
+ if (BaseCtor->isDeleted())
+ SetDeclDeleted(NewCtor, UsingLoc);
ClassDecl->addDecl(NewCtor);
result.first->second.second = NewCtor;
@@ -7240,6 +7839,35 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
}
}
+void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor) {
+ CXXRecordDecl *ClassDecl = Constructor->getParent();
+ assert(Constructor->getInheritedConstructor() &&
+ !Constructor->doesThisDeclarationHaveABody() &&
+ !Constructor->isDeleted());
+
+ SynthesizedFunctionScope Scope(*this, Constructor);
+ DiagnosticErrorTrap Trap(Diags);
+ if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) ||
+ Trap.hasErrorOccurred()) {
+ Diag(CurrentLocation, diag::note_inhctor_synthesized_at)
+ << Context.getTagDeclType(ClassDecl);
+ Constructor->setInvalidDecl();
+ return;
+ }
+
+ SourceLocation Loc = Constructor->getLocation();
+ Constructor->setBody(new (Context) CompoundStmt(Loc));
+
+ Constructor->setUsed();
+ MarkVTableUsed(CurrentLocation, ClassDecl);
+
+ if (ASTMutationListener *L = getASTMutationListener()) {
+ L->CompletedImplicitDefinition(Constructor);
+ }
+}
+
+
Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) {
CXXRecordDecl *ClassDecl = MD->getParent();
@@ -7290,6 +7918,11 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
// If a class has no user-declared destructor, a destructor is
// declared implicitly. An implicitly-declared destructor is an
// inline public member of its class.
+ assert(ClassDecl->needsImplicitDestructor());
+
+ DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor);
+ if (DSM.isAlreadyBeingDeclared())
+ return 0;
// Create the actual destructor declaration.
CanQualType ClassType
@@ -7305,13 +7938,23 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
Destructor->setAccess(AS_public);
Destructor->setDefaulted();
Destructor->setImplicit();
- Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
// Build an exception specification pointing back at this destructor.
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = Destructor;
- Destructor->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
+ Destructor->setType(Context.getFunctionType(Context.VoidTy,
+ ArrayRef<QualType>(),
+ EPI));
+
+ AddOverriddenMethods(ClassDecl, Destructor);
+
+ // We don't need to use SpecialMemberIsTrivial here; triviality for
+ // destructors is easy to compute.
+ Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+
+ if (ShouldDeleteSpecialMember(Destructor, CXXDestructor))
+ SetDeclDeleted(Destructor, ClassLoc);
// Note that we have declared this destructor.
++ASTContext::NumImplicitDestructorsDeclared;
@@ -7321,11 +7964,6 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
PushOnScopeChains(Destructor, S, false);
ClassDecl->addDecl(Destructor);
- AddOverriddenMethods(ClassDecl, Destructor);
-
- if (ShouldDeleteSpecialMember(Destructor, CXXDestructor))
- Destructor->setDeletedAsWritten();
-
return Destructor;
}
@@ -7369,6 +8007,14 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
/// \brief Perform any semantic analysis which needs to be delayed until all
/// pending class member declarations have been parsed.
void Sema::ActOnFinishCXXMemberDecls() {
+ // If the context is an invalid C++ class, just suppress these checks.
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
+ if (Record->isInvalidDecl()) {
+ DelayedDestructorExceptionSpecChecks.clear();
+ return;
+ }
+ }
+
// Perform any deferred checking of exception specifications for virtual
// destructors.
for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size();
@@ -7385,7 +8031,7 @@ void Sema::ActOnFinishCXXMemberDecls() {
void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
CXXDestructorDecl *Destructor) {
- assert(getLangOpts().CPlusPlus0x &&
+ assert(getLangOpts().CPlusPlus11 &&
"adjusting dtor exception specs was introduced in c++11");
// C++11 [class.dtor]p3:
@@ -7403,7 +8049,9 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo();
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = Destructor;
- Destructor->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
+ Destructor->setType(Context.getFunctionType(Context.VoidTy,
+ ArrayRef<QualType>(),
+ EPI));
// FIXME: If the destructor has a body that could throw, and the newly created
// spec doesn't allow exceptions, we should emit a warning, because this
@@ -7412,6 +8060,60 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
// needs to be done somewhere else.
}
+/// When generating a defaulted copy or move assignment operator, if a field
+/// should be copied with __builtin_memcpy rather than via explicit assignments,
+/// do so. This optimization only applies for arrays of scalars, and for arrays
+/// of class type where the selected copy/move-assignment operator is trivial.
+static StmtResult
+buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
+ Expr *To, Expr *From) {
+ // Compute the size of the memory buffer to be copied.
+ QualType SizeType = S.Context.getSizeType();
+ llvm::APInt Size(S.Context.getTypeSize(SizeType),
+ S.Context.getTypeSizeInChars(T).getQuantity());
+
+ // Take the address of the field references for "from" and "to". We
+ // directly construct UnaryOperators here because semantic analysis
+ // does not permit us to take the address of an xvalue.
+ From = new (S.Context) UnaryOperator(From, UO_AddrOf,
+ S.Context.getPointerType(From->getType()),
+ VK_RValue, OK_Ordinary, Loc);
+ To = new (S.Context) UnaryOperator(To, UO_AddrOf,
+ S.Context.getPointerType(To->getType()),
+ VK_RValue, OK_Ordinary, Loc);
+
+ const Type *E = T->getBaseElementTypeUnsafe();
+ bool NeedsCollectableMemCpy =
+ E->isRecordType() && E->getAs<RecordType>()->getDecl()->hasObjectMember();
+
+ // Create a reference to the __builtin_objc_memmove_collectable function
+ StringRef MemCpyName = NeedsCollectableMemCpy ?
+ "__builtin_objc_memmove_collectable" :
+ "__builtin_memcpy";
+ LookupResult R(S, &S.Context.Idents.get(MemCpyName), Loc,
+ Sema::LookupOrdinaryName);
+ S.LookupName(R, S.TUScope, true);
+
+ FunctionDecl *MemCpy = R.getAsSingle<FunctionDecl>();
+ if (!MemCpy)
+ // Something went horribly wrong earlier, and we will have complained
+ // about it.
+ return StmtError();
+
+ ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
+ VK_RValue, Loc, 0);
+ assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");
+
+ Expr *CallArgs[] = {
+ To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc)
+ };
+ ExprResult Call = S.ActOnCallExpr(/*Scope=*/0, MemCpyRef.take(),
+ Loc, CallArgs, Loc);
+
+ assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
+ return S.Owned(Call.takeAs<Stmt>());
+}
+
/// \brief Builds a statement that copies/moves the given entity from \p From to
/// \c To.
///
@@ -7437,13 +8139,14 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
///
/// \param Depth Internal parameter recording the depth of the recursion.
///
-/// \returns A statement or a loop that copies the expressions.
+/// \returns A statement or a loop that copies the expressions, or StmtResult(0)
+/// if a memcpy should be used instead.
static StmtResult
-BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
- Expr *To, Expr *From,
- bool CopyingBaseSubobject, bool Copying,
- unsigned Depth = 0) {
- // C++0x [class.copy]p28:
+buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
+ Expr *To, Expr *From,
+ bool CopyingBaseSubobject, bool Copying,
+ unsigned Depth = 0) {
+ // C++11 [class.copy]p28:
// Each subobject is assigned in the manner appropriate to its type:
//
// - if the subobject is of class type, as if by a call to operator= with
@@ -7451,32 +8154,41 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
// subobject of x as a single function argument (as if by explicit
// qualification; that is, ignoring any possible virtual overriding
// functions in more derived classes);
+ //
+ // C++03 [class.copy]p13:
+ // - if the subobject is of class type, the copy assignment operator for
+ // the class is used (as if by explicit qualification; that is,
+ // ignoring any possible virtual overriding functions in more derived
+ // classes);
if (const RecordType *RecordTy = T->getAs<RecordType>()) {
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
-
+
// Look for operator=.
DeclarationName Name
= S.Context.DeclarationNames.getCXXOperatorName(OO_Equal);
LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName);
S.LookupQualifiedName(OpLookup, ClassDecl, false);
-
- // Filter out any result that isn't a copy/move-assignment operator.
- LookupResult::Filter F = OpLookup.makeFilter();
- while (F.hasNext()) {
- NamedDecl *D = F.next();
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
- if (Method->isCopyAssignmentOperator() ||
- (!Copying && Method->isMoveAssignmentOperator()))
- continue;
- F.erase();
+ // Prior to C++11, filter out any result that isn't a copy/move-assignment
+ // operator.
+ if (!S.getLangOpts().CPlusPlus11) {
+ LookupResult::Filter F = OpLookup.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next();
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+ if (Method->isCopyAssignmentOperator() ||
+ (!Copying && Method->isMoveAssignmentOperator()))
+ continue;
+
+ F.erase();
+ }
+ F.done();
}
- F.done();
-
+
// Suppress the protected check (C++ [class.protected]) for each of the
- // assignment operators we found. This strange dance is required when
+ // assignment operators we found. This strange dance is required when
// we're assigning via a base classes's copy-assignment operator. To
- // ensure that we're getting the right base class subobject (without
+ // ensure that we're getting the right base class subobject (without
// ambiguities), we need to cast "this" to that subobject type; to
// ensure that we don't go through the virtual call mechanism, we need
// to qualify the operator= name with the base class (see below). However,
@@ -7491,20 +8203,20 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
L.setAccess(AS_public);
}
}
-
+
// Create the nested-name-specifier that will be used to qualify the
// reference to operator=; this is required to suppress the virtual
// call mechanism.
CXXScopeSpec SS;
const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
- SS.MakeTrivial(S.Context,
- NestedNameSpecifier::Create(S.Context, 0, false,
+ SS.MakeTrivial(S.Context,
+ NestedNameSpecifier::Create(S.Context, 0, false,
CanonicalT),
Loc);
-
+
// Create the reference to operator=.
ExprResult OpEqualRef
- = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS,
+ = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS,
/*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/0,
OpLookup,
@@ -7512,39 +8224,46 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
/*SuppressQualifierCheck=*/true);
if (OpEqualRef.isInvalid())
return StmtError();
-
+
// Build the call to the assignment operator.
- ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
+ ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
OpEqualRef.takeAs<Expr>(),
Loc, &From, 1, Loc);
if (Call.isInvalid())
return StmtError();
-
- return S.Owned(Call.takeAs<Stmt>());
+
+ // If we built a call to a trivial 'operator=' while copying an array,
+ // bail out. We'll replace the whole shebang with a memcpy.
+ CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Call.get());
+ if (CE && CE->getMethodDecl()->isTrivial() && Depth)
+ return StmtResult((Stmt*)0);
+
+ // Convert to an expression-statement, and clean up any produced
+ // temporaries.
+ return S.ActOnExprStmt(Call);
}
- // - if the subobject is of scalar type, the built-in assignment
+ // - if the subobject is of scalar type, the built-in assignment
// operator is used.
- const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);
+ const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);
if (!ArrayTy) {
ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From);
if (Assignment.isInvalid())
return StmtError();
-
- return S.Owned(Assignment.takeAs<Stmt>());
+ return S.ActOnExprStmt(Assignment);
}
-
- // - if the subobject is an array, each element is assigned, in the
+
+ // - if the subobject is an array, each element is assigned, in the
// manner appropriate to the element type;
-
+
// Construct a loop over the array bounds, e.g.,
//
// for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0)
//
// that will copy each of the array elements.
QualType SizeType = S.Context.getSizeType();
-
+
// Create the iteration variable.
IdentifierInfo *IterationVarName = 0;
{
@@ -7556,8 +8275,8 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
IterationVarName, SizeType,
S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None, SC_None);
-
+ SC_None);
+
// Initialize the iteration variable to zero.
llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));
@@ -7572,7 +8291,26 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
// Create the DeclStmt that holds the iteration variable.
Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc);
-
+
+ // Subscript the "from" and "to" expressions with the iteration variable.
+ From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
+ IterationVarRefRVal,
+ Loc));
+ To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc,
+ IterationVarRefRVal,
+ Loc));
+ if (!Copying) // Cast to rvalue
+ From = CastForMoving(S, From);
+
+ // Build the copy/move for an individual element of the array.
+ StmtResult Copy =
+ buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(),
+ To, From, CopyingBaseSubobject,
+ Copying, Depth + 1);
+ // Bail out if copying fails or if we determined that we should use memcpy.
+ if (Copy.isInvalid() || !Copy.get())
+ return Copy;
+
// Create the comparison against the array bound.
llvm::APInt Upper
= ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType));
@@ -7581,104 +8319,38 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
BO_NE, S.Context.BoolTy,
VK_RValue, OK_Ordinary, Loc, false);
-
+
// Create the pre-increment of the iteration variable.
Expr *Increment
= new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType,
VK_LValue, OK_Ordinary, Loc);
-
- // Subscript the "from" and "to" expressions with the iteration variable.
- From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
- IterationVarRefRVal,
- Loc));
- To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc,
- IterationVarRefRVal,
- Loc));
- if (!Copying) // Cast to rvalue
- From = CastForMoving(S, From);
- // Build the copy/move for an individual element of the array.
- StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(),
- To, From, CopyingBaseSubobject,
- Copying, Depth + 1);
- if (Copy.isInvalid())
- return StmtError();
-
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(Loc, Loc, InitStmt,
S.MakeFullExpr(Comparison),
- 0, S.MakeFullExpr(Increment),
+ 0, S.MakeFullDiscardedValueExpr(Increment),
Loc, Copy.take());
}
-/// Determine whether an implicit copy assignment operator for ClassDecl has a
-/// const argument.
-/// FIXME: It ought to be possible to store this on the record.
-static bool isImplicitCopyAssignmentArgConst(Sema &S,
- CXXRecordDecl *ClassDecl) {
- if (ClassDecl->isInvalidDecl())
- return true;
+static StmtResult
+buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
+ Expr *To, Expr *From,
+ bool CopyingBaseSubobject, bool Copying) {
+ // Maybe we should use a memcpy?
+ if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() &&
+ T.isTriviallyCopyableType(S.Context))
+ return buildMemcpyForAssignmentOp(S, Loc, T, To, From);
- // C++ [class.copy]p10:
- // If the class definition does not explicitly declare a copy
- // assignment operator, one is declared implicitly.
- // The implicitly-defined copy assignment operator for a class X
- // will have the form
- //
- // X& X::operator=(const X&)
- //
- // if
- // -- each direct base class B of X has a copy assignment operator
- // whose parameter is of type const B&, const volatile B& or B,
- // and
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- // We'll handle this below
- if (S.getLangOpts().CPlusPlus0x && Base->isVirtual())
- continue;
+ StmtResult Result(buildSingleCopyAssignRecursively(S, Loc, T, To, From,
+ CopyingBaseSubobject,
+ Copying, 0));
- assert(!Base->getType()->isDependentType() &&
- "Cannot generate implicit members for class with dependent bases.");
- CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl();
- if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, false, 0))
- return false;
- }
+ // If we ended up picking a trivial assignment operator for an array of a
+ // non-trivially-copyable class type, just emit a memcpy.
+ if (!Result.isInvalid() && !Result.get())
+ return buildMemcpyForAssignmentOp(S, Loc, T, To, From);
- // In C++11, the above citation has "or virtual" added
- if (S.getLangOpts().CPlusPlus0x) {
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
- assert(!Base->getType()->isDependentType() &&
- "Cannot generate implicit members for class with dependent bases.");
- CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl();
- if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const,
- false, 0))
- return false;
- }
- }
-
- // -- for all the nonstatic data members of X that are of a class
- // type M (or array thereof), each such class type has a copy
- // assignment operator whose parameter is of type const M&,
- // const volatile M& or M.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
- QualType FieldType = S.Context.getBaseElementType(Field->getType());
- if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl())
- if (!S.LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const,
- false, 0))
- return false;
- }
-
- // Otherwise, the implicitly declared copy assignment operator will
- // have the form
- //
- // X& X::operator=(X&)
-
- return true;
+ return Result;
}
Sema::ImplicitExceptionSpecification
@@ -7748,10 +8420,15 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
// constructor rules. Note that virtual bases are not taken into account
// for determining the argument type of the operator. Note also that
// operators taking an object instead of a reference are allowed.
+ assert(ClassDecl->needsImplicitCopyAssignment());
+
+ DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment);
+ if (DSM.isAlreadyBeingDeclared())
+ return 0;
QualType ArgType = Context.getTypeDeclType(ClassDecl);
QualType RetType = Context.getLValueReferenceType(ArgType);
- if (isImplicitCopyAssignmentArgConst(*this, ClassDecl))
+ if (ClassDecl->implicitCopyAssignmentHasConstParam())
ArgType = ArgType.withConst();
ArgType = Context.getLValueReferenceType(ArgType);
@@ -7762,45 +8439,49 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *CopyAssignment
= CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0, /*isStatic=*/false,
- /*StorageClassAsWritten=*/SC_None,
+ /*TInfo=*/0,
+ /*StorageClass=*/SC_None,
/*isInline=*/true, /*isConstexpr=*/false,
SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setDefaulted();
CopyAssignment->setImplicit();
- CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = CopyAssignment;
- CopyAssignment->setType(Context.getFunctionType(RetType, &ArgType, 1, EPI));
+ CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
ClassLoc, ClassLoc, /*Id=*/0,
ArgType, /*TInfo=*/0,
- SC_None,
SC_None, 0);
CopyAssignment->setParams(FromParam);
-
- // Note that we have added this copy-assignment operator.
- ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
- if (Scope *S = getScopeForContext(ClassDecl))
- PushOnScopeChains(CopyAssignment, S, false);
- ClassDecl->addDecl(CopyAssignment);
-
+ AddOverriddenMethods(ClassDecl, CopyAssignment);
+
+ CopyAssignment->setTrivial(
+ ClassDecl->needsOverloadResolutionForCopyAssignment()
+ ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
+ : ClassDecl->hasTrivialCopyAssignment());
+
// C++0x [class.copy]p19:
// .... If the class definition does not explicitly declare a copy
// assignment operator, there is no user-declared move constructor, and
// there is no user-declared move assignment operator, a copy assignment
// operator is implicitly declared as defaulted.
if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
- CopyAssignment->setDeletedAsWritten();
+ SetDeclDeleted(CopyAssignment, ClassLoc);
+
+ // Note that we have added this copy-assignment operator.
+ ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
+
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(CopyAssignment, S, false);
+ ClassDecl->addDecl(CopyAssignment);
- AddOverriddenMethods(ClassDecl, CopyAssignment);
return CopyAssignment;
}
@@ -7892,7 +8573,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
VK_LValue, &BasePath);
// Build the copy.
- StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType,
+ StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType,
To.get(), From,
/*CopyingBaseSubobject=*/true,
/*Copying=*/true);
@@ -7907,11 +8588,6 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
Statements.push_back(Copy.takeAs<Expr>());
}
- // \brief Reference to the __builtin_memcpy function.
- Expr *BuiltinMemCpyRef = 0;
- // \brief Reference to the __builtin_objc_memmove_collectable function.
- Expr *CollectableMemCpyRef = 0;
-
// Assign non-static members.
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
FieldEnd = ClassDecl->field_end();
@@ -7969,99 +8645,9 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
MemberLookup, 0);
assert(!From.isInvalid() && "Implicit field reference cannot fail");
assert(!To.isInvalid() && "Implicit field reference cannot fail");
-
- // If the field should be copied with __builtin_memcpy rather than via
- // explicit assignments, do so. This optimization only applies for arrays
- // of scalars and arrays of class type with trivial copy-assignment
- // operators.
- if (FieldType->isArrayType() && !FieldType.isVolatileQualified()
- && BaseType.hasTrivialAssignment(Context, /*Copying=*/true)) {
- // Compute the size of the memory buffer to be copied.
- QualType SizeType = Context.getSizeType();
- llvm::APInt Size(Context.getTypeSize(SizeType),
- Context.getTypeSizeInChars(BaseType).getQuantity());
- for (const ConstantArrayType *Array
- = Context.getAsConstantArrayType(FieldType);
- Array;
- Array = Context.getAsConstantArrayType(Array->getElementType())) {
- llvm::APInt ArraySize
- = Array->getSize().zextOrTrunc(Size.getBitWidth());
- Size *= ArraySize;
- }
-
- // Take the address of the field references for "from" and "to".
- From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get());
- To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get());
-
- bool NeedsCollectableMemCpy =
- (BaseType->isRecordType() &&
- BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
-
- if (NeedsCollectableMemCpy) {
- if (!CollectableMemCpyRef) {
- // Create a reference to the __builtin_objc_memmove_collectable function.
- LookupResult R(*this,
- &Context.Idents.get("__builtin_objc_memmove_collectable"),
- Loc, LookupOrdinaryName);
- LookupName(R, TUScope, true);
-
- FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
- if (!CollectableMemCpy) {
- // Something went horribly wrong earlier, and we will have
- // complained about it.
- Invalid = true;
- continue;
- }
-
- CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy,
- Context.BuiltinFnTy,
- VK_RValue, Loc, 0).take();
- assert(CollectableMemCpyRef && "Builtin reference cannot fail");
- }
- }
- // Create a reference to the __builtin_memcpy builtin function.
- else if (!BuiltinMemCpyRef) {
- LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
- LookupOrdinaryName);
- LookupName(R, TUScope, true);
-
- FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>();
- if (!BuiltinMemCpy) {
- // Something went horribly wrong earlier, and we will have complained
- // about it.
- Invalid = true;
- continue;
- }
- BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy,
- Context.BuiltinFnTy,
- VK_RValue, Loc, 0).take();
- assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
- }
-
- SmallVector<Expr*, 8> CallArgs;
- CallArgs.push_back(To.takeAs<Expr>());
- CallArgs.push_back(From.takeAs<Expr>());
- CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
- ExprResult Call = ExprError();
- if (NeedsCollectableMemCpy)
- Call = ActOnCallExpr(/*Scope=*/0,
- CollectableMemCpyRef,
- Loc, CallArgs,
- Loc);
- else
- Call = ActOnCallExpr(/*Scope=*/0,
- BuiltinMemCpyRef,
- Loc, CallArgs,
- Loc);
-
- assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
- Statements.push_back(Call.takeAs<Expr>());
- continue;
- }
-
// Build the copy of this field.
- StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType,
+ StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType,
To.get(), From.get(),
/*CopyingBaseSubobject=*/false,
/*Copying=*/true);
@@ -8188,10 +8774,7 @@ hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) {
if (BaseClass->needsImplicitMoveAssignment())
S.DeclareImplicitMoveAssignment(BaseClass);
- // If the class has both a trivial move assignment and a non-trivial move
- // assignment, hasTrivialMoveAssignment() is false.
- if (BaseClass->hasDeclaredMoveAssignment() &&
- !BaseClass->hasTrivialMoveAssignment())
+ if (BaseClass->hasNonTrivialMoveAssignment())
return true;
}
@@ -8215,14 +8798,18 @@ hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) {
return true;
if (IsConstructor) {
+ // FIXME: Need this because otherwise hasMoveConstructor isn't guaranteed to
+ // give the right answer.
if (ClassDecl->needsImplicitMoveConstructor())
S.DeclareImplicitMoveConstructor(ClassDecl);
- return ClassDecl->hasDeclaredMoveConstructor();
+ return ClassDecl->hasMoveConstructor();
}
+ // FIXME: Need this because otherwise hasMoveAssignment isn't guaranteed to
+ // give the right answer.
if (ClassDecl->needsImplicitMoveAssignment())
S.DeclareImplicitMoveAssignment(ClassDecl);
- return ClassDecl->hasDeclaredMoveAssignment();
+ return ClassDecl->hasMoveAssignment();
}
/// Determine whether all non-static data members and direct or virtual bases
@@ -8266,6 +8853,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
// - [first 4 bullets]
assert(ClassDecl->needsImplicitMoveAssignment());
+ DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);
+ if (DSM.isAlreadyBeingDeclared())
+ return 0;
+
// [Checked after we build the declaration]
// - the move assignment operator would not be implicitly defined as
// deleted,
@@ -8296,32 +8887,34 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *MoveAssignment
= CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0, /*isStatic=*/false,
- /*StorageClassAsWritten=*/SC_None,
+ /*TInfo=*/0,
+ /*StorageClass=*/SC_None,
/*isInline=*/true,
/*isConstexpr=*/false,
SourceLocation());
MoveAssignment->setAccess(AS_public);
MoveAssignment->setDefaulted();
MoveAssignment->setImplicit();
- MoveAssignment->setTrivial(ClassDecl->hasTrivialMoveAssignment());
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = MoveAssignment;
- MoveAssignment->setType(Context.getFunctionType(RetType, &ArgType, 1, EPI));
+ MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
ClassLoc, ClassLoc, /*Id=*/0,
ArgType, /*TInfo=*/0,
- SC_None,
SC_None, 0);
MoveAssignment->setParams(FromParam);
- // Note that we have added this copy-assignment operator.
- ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
+ AddOverriddenMethods(ClassDecl, MoveAssignment);
+
+ MoveAssignment->setTrivial(
+ ClassDecl->needsOverloadResolutionForMoveAssignment()
+ ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
+ : ClassDecl->hasTrivialMoveAssignment());
// C++0x [class.copy]p9:
// If the definition of a class X does not explicitly declare a move
@@ -8337,11 +8930,13 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
return 0;
}
+ // Note that we have added this copy-assignment operator.
+ ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
+
if (Scope *S = getScopeForContext(ClassDecl))
PushOnScopeChains(MoveAssignment, S, false);
ClassDecl->addDecl(MoveAssignment);
- AddOverriddenMethods(ClassDecl, MoveAssignment);
return MoveAssignment;
}
@@ -8431,7 +9026,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
VK_LValue, &BasePath);
// Build the move.
- StmtResult Move = BuildSingleCopyAssign(*this, Loc, BaseType,
+ StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType,
To.get(), From,
/*CopyingBaseSubobject=*/true,
/*Copying=*/false);
@@ -8446,11 +9041,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
Statements.push_back(Move.takeAs<Expr>());
}
- // \brief Reference to the __builtin_memcpy function.
- Expr *BuiltinMemCpyRef = 0;
- // \brief Reference to the __builtin_objc_memmove_collectable function.
- Expr *CollectableMemCpyRef = 0;
-
// Assign non-static members.
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
FieldEnd = ClassDecl->field_end();
@@ -8513,104 +9103,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
"Member reference with rvalue base must be rvalue except for reference "
"members, which aren't allowed for move assignment.");
- // If the field should be copied with __builtin_memcpy rather than via
- // explicit assignments, do so. This optimization only applies for arrays
- // of scalars and arrays of class type with trivial move-assignment
- // operators.
- if (FieldType->isArrayType() && !FieldType.isVolatileQualified()
- && BaseType.hasTrivialAssignment(Context, /*Copying=*/false)) {
- // Compute the size of the memory buffer to be copied.
- QualType SizeType = Context.getSizeType();
- llvm::APInt Size(Context.getTypeSize(SizeType),
- Context.getTypeSizeInChars(BaseType).getQuantity());
- for (const ConstantArrayType *Array
- = Context.getAsConstantArrayType(FieldType);
- Array;
- Array = Context.getAsConstantArrayType(Array->getElementType())) {
- llvm::APInt ArraySize
- = Array->getSize().zextOrTrunc(Size.getBitWidth());
- Size *= ArraySize;
- }
-
- // Take the address of the field references for "from" and "to". We
- // directly construct UnaryOperators here because semantic analysis
- // does not permit us to take the address of an xvalue.
- From = new (Context) UnaryOperator(From.get(), UO_AddrOf,
- Context.getPointerType(From.get()->getType()),
- VK_RValue, OK_Ordinary, Loc);
- To = new (Context) UnaryOperator(To.get(), UO_AddrOf,
- Context.getPointerType(To.get()->getType()),
- VK_RValue, OK_Ordinary, Loc);
-
- bool NeedsCollectableMemCpy =
- (BaseType->isRecordType() &&
- BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
-
- if (NeedsCollectableMemCpy) {
- if (!CollectableMemCpyRef) {
- // Create a reference to the __builtin_objc_memmove_collectable function.
- LookupResult R(*this,
- &Context.Idents.get("__builtin_objc_memmove_collectable"),
- Loc, LookupOrdinaryName);
- LookupName(R, TUScope, true);
-
- FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
- if (!CollectableMemCpy) {
- // Something went horribly wrong earlier, and we will have
- // complained about it.
- Invalid = true;
- continue;
- }
-
- CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy,
- Context.BuiltinFnTy,
- VK_RValue, Loc, 0).take();
- assert(CollectableMemCpyRef && "Builtin reference cannot fail");
- }
- }
- // Create a reference to the __builtin_memcpy builtin function.
- else if (!BuiltinMemCpyRef) {
- LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
- LookupOrdinaryName);
- LookupName(R, TUScope, true);
-
- FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>();
- if (!BuiltinMemCpy) {
- // Something went horribly wrong earlier, and we will have complained
- // about it.
- Invalid = true;
- continue;
- }
-
- BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy,
- Context.BuiltinFnTy,
- VK_RValue, Loc, 0).take();
- assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
- }
-
- SmallVector<Expr*, 8> CallArgs;
- CallArgs.push_back(To.takeAs<Expr>());
- CallArgs.push_back(From.takeAs<Expr>());
- CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
- ExprResult Call = ExprError();
- if (NeedsCollectableMemCpy)
- Call = ActOnCallExpr(/*Scope=*/0,
- CollectableMemCpyRef,
- Loc, CallArgs,
- Loc);
- else
- Call = ActOnCallExpr(/*Scope=*/0,
- BuiltinMemCpyRef,
- Loc, CallArgs,
- Loc);
-
- assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
- Statements.push_back(Call.takeAs<Expr>());
- continue;
- }
-
// Build the move of this field.
- StmtResult Move = BuildSingleCopyAssign(*this, Loc, FieldType,
+ StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType,
To.get(), From.get(),
/*CopyingBaseSubobject=*/false,
/*Copying=*/false);
@@ -8620,7 +9114,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
MoveAssignOperator->setInvalidDecl();
return;
}
-
+
// Success! Record the copy.
Statements.push_back(Move.takeAs<Stmt>());
}
@@ -8662,70 +9156,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
}
-/// Determine whether an implicit copy constructor for ClassDecl has a const
-/// argument.
-/// FIXME: It ought to be possible to store this on the record.
-static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl *ClassDecl) {
- if (ClassDecl->isInvalidDecl())
- return true;
-
- // C++ [class.copy]p5:
- // The implicitly-declared copy constructor for a class X will
- // have the form
- //
- // X::X(const X&)
- //
- // if
- // -- each direct or virtual base class B of X has a copy
- // constructor whose first parameter is of type const B& or
- // const volatile B&, and
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- // Virtual bases are handled below.
- if (Base->isVirtual())
- continue;
-
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- // FIXME: This lookup is wrong. If the copy ctor for a member or base is
- // ambiguous, we should still produce a constructor with a const-qualified
- // parameter.
- if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const))
- return false;
- }
-
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const))
- return false;
- }
-
- // -- for all the nonstatic data members of X that are of a
- // class type M (or array thereof), each such class type
- // has a copy constructor whose first parameter is of type
- // const M& or const volatile M&.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
- QualType FieldType = S.Context.getBaseElementType(Field->getType());
- if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
- if (!S.LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const))
- return false;
- }
- }
-
- // Otherwise, the implicitly declared copy constructor will have
- // the form
- //
- // X::X(X&)
-
- return true;
-}
-
Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD) {
CXXRecordDecl *ClassDecl = MD->getParent();
@@ -8786,10 +9216,15 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
// C++ [class.copy]p4:
// If the class definition does not explicitly declare a copy
// constructor, one is declared implicitly.
+ assert(ClassDecl->needsImplicitCopyConstructor());
+
+ DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor);
+ if (DSM.isAlreadyBeingDeclared())
+ return 0;
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = ClassType;
- bool Const = isImplicitCopyCtorArgConst(*this, ClassDecl);
+ bool Const = ClassDecl->implicitCopyConstructorHasConstParam();
if (Const)
ArgType = ArgType.withConst();
ArgType = Context.getLValueReferenceType(ArgType);
@@ -8812,30 +9247,26 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
Constexpr);
CopyConstructor->setAccess(AS_public);
CopyConstructor->setDefaulted();
- CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = CopyConstructor;
CopyConstructor->setType(
- Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
+ Context.getFunctionType(Context.VoidTy, ArgType, EPI));
- // Note that we have declared this constructor.
- ++ASTContext::NumImplicitCopyConstructorsDeclared;
-
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
ClassLoc, ClassLoc,
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
- SC_None,
SC_None, 0);
CopyConstructor->setParams(FromParam);
- if (Scope *S = getScopeForContext(ClassDecl))
- PushOnScopeChains(CopyConstructor, S, false);
- ClassDecl->addDecl(CopyConstructor);
+ CopyConstructor->setTrivial(
+ ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
+ : ClassDecl->hasTrivialCopyConstructor());
// C++11 [class.copy]p8:
// ... If the class definition does not explicitly declare a copy
@@ -8843,7 +9274,14 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
// user-declared move assignment operator, a copy constructor is implicitly
// declared as defaulted.
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
- CopyConstructor->setDeletedAsWritten();
+ SetDeclDeleted(CopyConstructor, ClassLoc);
+
+ // Note that we have declared this constructor.
+ ++ASTContext::NumImplicitCopyConstructorsDeclared;
+
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(CopyConstructor, S, false);
+ ClassDecl->addDecl(CopyConstructor);
return CopyConstructor;
}
@@ -8862,7 +9300,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
SynthesizedFunctionScope Scope(*this, CopyConstructor);
DiagnosticErrorTrap Trap(Diags);
- if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) ||
+ if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false) ||
Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
@@ -8957,6 +9395,10 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
// - [first 4 bullets]
assert(ClassDecl->needsImplicitMoveConstructor());
+ DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);
+ if (DSM.isAlreadyBeingDeclared())
+ return 0;
+
// [Checked after we build the declaration]
// - the move assignment operator would not be implicitly defined as
// deleted,
@@ -8991,24 +9433,27 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
Constexpr);
MoveConstructor->setAccess(AS_public);
MoveConstructor->setDefaulted();
- MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor());
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = MoveConstructor;
MoveConstructor->setType(
- Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
+ Context.getFunctionType(Context.VoidTy, ArgType, EPI));
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
ClassLoc, ClassLoc,
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
- SC_None,
SC_None, 0);
MoveConstructor->setParams(FromParam);
+ MoveConstructor->setTrivial(
+ ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
+ : ClassDecl->hasTrivialMoveConstructor());
+
// C++0x [class.copy]p9:
// If the definition of a class X does not explicitly declare a move
// constructor, one will be implicitly declared as defaulted if and only if:
@@ -9045,7 +9490,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
SynthesizedFunctionScope Scope(*this, MoveConstructor);
DiagnosticErrorTrap Trap(Diags);
- if (SetCtorInitializers(MoveConstructor, 0, 0, /*AnyErrors=*/false) ||
+ if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false) ||
Trap.hasErrorOccurred()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXMoveConstructor << Context.getTagDeclType(ClassDecl);
@@ -9077,8 +9522,8 @@ bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) {
CXXMethodDecl *CallOperator
= cast<CXXMethodDecl>(
- *Lambda->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first);
+ Lambda->lookup(
+ S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).front());
CallOperator->setReferenced();
CallOperator->setUsed();
}
@@ -9100,12 +9545,12 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
// Return the address of the __invoke function.
DeclarationName InvokeName = &Context.Idents.get("__invoke");
CXXMethodDecl *Invoke
- = cast<CXXMethodDecl>(*Lambda->lookup(InvokeName).first);
+ = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front());
Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
VK_LValue, Conv->getLocation()).take();
assert(FunctionRef && "Can't refer to __invoke function?");
Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
- Conv->setBody(new (Context) CompoundStmt(Context, &Return, 1,
+ Conv->setBody(new (Context) CompoundStmt(Context, Return,
Conv->getLocation(),
Conv->getLocation()));
@@ -9164,7 +9609,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
// Set the body of the conversion function.
Stmt *ReturnS = Return.take();
- Conv->setBody(new (Context) CompoundStmt(Context, &ReturnS, 1,
+ Conv->setBody(new (Context) CompoundStmt(Context, ReturnS,
Conv->getLocation(),
Conv->getLocation()));
@@ -9198,6 +9643,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
+ bool IsListInitialization,
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
@@ -9221,7 +9667,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
Elidable, ExprArgs, HadMultipleCandidates,
- RequiresZeroInit, ConstructKind, ParenRange);
+ IsListInitialization, RequiresZeroInit,
+ ConstructKind, ParenRange);
}
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
@@ -9231,39 +9678,19 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, bool Elidable,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
+ bool IsListInitialization,
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
MarkFunctionReferenced(ConstructLoc, Constructor);
return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
Constructor, Elidable, ExprArgs,
- HadMultipleCandidates, /*FIXME*/false,
- RequiresZeroInit,
+ HadMultipleCandidates,
+ IsListInitialization, RequiresZeroInit,
static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
ParenRange));
}
-bool Sema::InitializeVarWithConstructor(VarDecl *VD,
- CXXConstructorDecl *Constructor,
- MultiExprArg Exprs,
- bool HadMultipleCandidates) {
- // FIXME: Provide the correct paren SourceRange when available.
- ExprResult TempResult =
- BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor,
- Exprs, HadMultipleCandidates, false,
- CXXConstructExpr::CK_Complete, SourceRange());
- if (TempResult.isInvalid())
- return true;
-
- Expr *Temp = TempResult.takeAs<Expr>();
- CheckImplicitConversions(Temp, VD->getLocation());
- MarkFunctionReferenced(VD->getLocation(), Constructor);
- Temp = MaybeCreateExprWithCleanups(Temp);
- VD->setInit(Temp);
-
- return false;
-}
-
void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
if (VD->isInvalidDecl()) return;
@@ -9301,7 +9728,8 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
MultiExprArg ArgsPtr,
SourceLocation Loc,
SmallVectorImpl<Expr*> &ConvertedArgs,
- bool AllowExplicit) {
+ bool AllowExplicit,
+ bool IsListInitialization) {
// FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
unsigned NumArgs = ArgsPtr.size();
Expr **Args = ArgsPtr.data();
@@ -9322,12 +9750,15 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
SmallVector<Expr *, 8> AllArgs;
bool Invalid = GatherArgumentsForCall(Loc, Constructor,
Proto, 0, Args, NumArgs, AllArgs,
- CallType, AllowExplicit);
+ CallType, AllowExplicit,
+ IsListInitialization);
ConvertedArgs.append(AllArgs.begin(), AllArgs.end());
DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size());
- CheckConstructorCall(Constructor, AllArgs.data(), AllArgs.size(),
+ CheckConstructorCall(Constructor,
+ llvm::makeArrayRef<const Expr *>(AllArgs.data(),
+ AllArgs.size()),
Proto, Loc);
return Invalid;
@@ -9766,6 +10197,19 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
return LinkageSpec;
}
+Decl *Sema::ActOnEmptyDeclaration(Scope *S,
+ AttributeList *AttrList,
+ SourceLocation SemiLoc) {
+ Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc);
+ // Attribute declarations appertain to empty declaration so we handle
+ // them here.
+ if (AttrList)
+ ProcessDeclAttributeList(S, ED, AttrList);
+
+ CurContext->addDecl(ED);
+ return ED;
+}
+
/// \brief Perform semantic analysis for the variable declaration that
/// occurs within a C++ catch clause, returning the newly-created
/// variable.
@@ -9833,7 +10277,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
}
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name,
- ExDeclType, TInfo, SC_None, SC_None);
+ ExDeclType, TInfo, SC_None);
ExDecl->setExceptionVariable(true);
// In ARC, infer 'retaining' for variables of retainable type.
@@ -9842,6 +10286,9 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
if (!Invalid && !ExDeclType->isDependentType()) {
if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) {
+ // Insulate this from anything else we might currently be parsing.
+ EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
+
// C++ [except.handle]p16:
// The object declared in an exception-declaration or, if the
// exception-declaration does not specify a name, a temporary (12.2) is
@@ -9893,8 +10340,8 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
bool Invalid = D.isInvalidType();
// Check for unexpanded parameter packs.
- if (TInfo && DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
- UPPC_ExceptionType)) {
+ if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+ UPPC_ExceptionType)) {
TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
D.getIdentifierLoc());
Invalid = true;
@@ -9970,7 +10417,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Failed = true;
if (!Failed && !Cond) {
- llvm::SmallString<256> MsgBuffer;
+ SmallString<256> MsgBuffer;
llvm::raw_svector_ostream Msg(MsgBuffer);
AssertMessage->printPretty(Msg, 0, getPrintingPolicy());
Diag(StaticAssertLoc, diag::err_static_assert_failed)
@@ -10007,47 +10454,49 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
// Do not complain about the form of friend template types during
// template instantiation; we will already have complained when the
// template was declared.
- } else if (!T->isElaboratedTypeSpecifier()) {
- // If we evaluated the type to a record type, suggest putting
- // a tag in front.
- if (const RecordType *RT = T->getAs<RecordType>()) {
- RecordDecl *RD = RT->getDecl();
+ } else {
+ if (!T->isElaboratedTypeSpecifier()) {
+ // If we evaluated the type to a record type, suggest putting
+ // a tag in front.
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ RecordDecl *RD = RT->getDecl();
- std::string InsertionText = std::string(" ") + RD->getKindName();
+ std::string InsertionText = std::string(" ") + RD->getKindName();
- Diag(TypeRange.getBegin(),
- getLangOpts().CPlusPlus0x ?
- diag::warn_cxx98_compat_unelaborated_friend_type :
- diag::ext_unelaborated_friend_type)
- << (unsigned) RD->getTagKind()
- << T
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc),
- InsertionText);
- } else {
+ Diag(TypeRange.getBegin(),
+ getLangOpts().CPlusPlus11 ?
+ diag::warn_cxx98_compat_unelaborated_friend_type :
+ diag::ext_unelaborated_friend_type)
+ << (unsigned) RD->getTagKind()
+ << T
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc),
+ InsertionText);
+ } else {
+ Diag(FriendLoc,
+ getLangOpts().CPlusPlus11 ?
+ diag::warn_cxx98_compat_nonclass_type_friend :
+ diag::ext_nonclass_type_friend)
+ << T
+ << TypeRange;
+ }
+ } else if (T->getAs<EnumType>()) {
Diag(FriendLoc,
- getLangOpts().CPlusPlus0x ?
- diag::warn_cxx98_compat_nonclass_type_friend :
- diag::ext_nonclass_type_friend)
+ getLangOpts().CPlusPlus11 ?
+ diag::warn_cxx98_compat_enum_friend :
+ diag::ext_enum_friend)
<< T
<< TypeRange;
}
- } else if (T->getAs<EnumType>()) {
- Diag(FriendLoc,
- getLangOpts().CPlusPlus0x ?
- diag::warn_cxx98_compat_enum_friend :
- diag::ext_enum_friend)
- << T
- << TypeRange;
- }
- // C++11 [class.friend]p3:
- // A friend declaration that does not declare a function shall have one
- // of the following forms:
- // friend elaborated-type-specifier ;
- // friend simple-type-specifier ;
- // friend typename-specifier ;
- if (getLangOpts().CPlusPlus0x && LocStart != FriendLoc)
- Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T;
+ // C++11 [class.friend]p3:
+ // A friend declaration that does not declare a function shall have one
+ // of the following forms:
+ // friend elaborated-type-specifier ;
+ // friend simple-type-specifier ;
+ // friend typename-specifier ;
+ if (getLangOpts().CPlusPlus11 && LocStart != FriendLoc)
+ Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T;
+ }
// If the type specifier in a friend declaration designates a (possibly
// cv-qualified) class type, that class is declared as a friend; otherwise,
@@ -10060,7 +10509,8 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
AttributeList *Attr,
MultiTemplateParamsArg TempParamLists) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
@@ -10132,19 +10582,20 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
- DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+ DependentNameTypeLoc TL =
+ TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
TL.setElaboratedKeywordLoc(TagLoc);
TL.setQualifierLoc(QualifierLoc);
TL.setNameLoc(NameLoc);
} else {
- ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
+ ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>();
TL.setElaboratedKeywordLoc(TagLoc);
TL.setQualifierLoc(QualifierLoc);
- cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc);
+ TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(NameLoc);
}
FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
- TSI, FriendLoc);
+ TSI, FriendLoc, TempParamLists);
Friend->setAccess(AS_public);
CurContext->addDecl(Friend);
return Friend;
@@ -10160,13 +10611,13 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
- DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+ DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
TL.setElaboratedKeywordLoc(TagLoc);
TL.setQualifierLoc(SS.getWithLocInContext(Context));
TL.setNameLoc(NameLoc);
FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
- TSI, FriendLoc);
+ TSI, FriendLoc, TempParamLists);
Friend->setAccess(AS_public);
Friend->setUnsupportedFriend(true);
CurContext->addDecl(Friend);
@@ -10260,8 +10711,8 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
return D;
}
-Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
- MultiTemplateParamsArg TemplateParams) {
+NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParams) {
const DeclSpec &DS = D.getDeclSpec();
assert(DS.isFriendSpecified());
@@ -10372,17 +10823,6 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DC = DC->getParent();
}
- // C++ [class.friend]p1: A friend of a class is a function or
- // class that is not a member of the class . . .
- // C++11 changes this for both friend types and functions.
- // Most C++ 98 compilers do seem to give an error here, so
- // we do, too.
- if (!Previous.empty() && DC->Equals(CurContext))
- Diag(DS.getFriendSpecLoc(),
- getLangOpts().CPlusPlus0x ?
- diag::warn_cxx98_compat_friend_is_member :
- diag::err_friend_is_member);
-
DCScope = getScopeForDeclContext(S, DC);
// C++ [class.friend]p6:
@@ -10427,7 +10867,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// class that is not a member of the class . . .
if (DC->Equals(CurContext))
Diag(DS.getFriendSpecLoc(),
- getLangOpts().CPlusPlus0x ?
+ getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_friend_is_member :
diag::err_friend_is_member);
@@ -10534,11 +10974,12 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
AdjustDeclIfTemplate(Dcl);
- FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl);
+ FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Dcl);
if (!Fn) {
Diag(DelLoc, diag::err_deleted_non_function);
return;
}
+
if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
// Don't consider the implicit declaration we generate for explicit
// specializations. FIXME: Do not generate these implicit declarations.
@@ -10549,41 +10990,34 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
}
// If the declaration wasn't the first, we delete the function anyway for
// recovery.
+ Fn = Fn->getCanonicalDecl();
}
- Fn->setDeletedAsWritten();
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl);
- if (!MD)
+ if (Fn->isDeleted())
return;
- // A deleted special member function is trivial if the corresponding
- // implicitly-declared function would have been.
- switch (getSpecialMember(MD)) {
- case CXXInvalid:
- break;
- case CXXDefaultConstructor:
- MD->setTrivial(MD->getParent()->hasTrivialDefaultConstructor());
- break;
- case CXXCopyConstructor:
- MD->setTrivial(MD->getParent()->hasTrivialCopyConstructor());
- break;
- case CXXMoveConstructor:
- MD->setTrivial(MD->getParent()->hasTrivialMoveConstructor());
- break;
- case CXXCopyAssignment:
- MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment());
- break;
- case CXXMoveAssignment:
- MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment());
- break;
- case CXXDestructor:
- MD->setTrivial(MD->getParent()->hasTrivialDestructor());
- break;
+ // See if we're deleting a function which is already known to override a
+ // non-deleted virtual function.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
+ bool IssuedDiagnostic = false;
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods();
+ I != E; ++I) {
+ if (!(*MD->begin_overridden_methods())->isDeleted()) {
+ if (!IssuedDiagnostic) {
+ Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
+ IssuedDiagnostic = true;
+ }
+ Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
+ }
+ }
}
+
+ Fn->setDeletedAsWritten();
}
void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl);
+ CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Dcl);
if (MD) {
if (MD->getParent()->isDependentType()) {
@@ -10609,11 +11043,19 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
// on it.
Pattern->isDefined(Primary);
+ // If the method was defaulted on its first declaration, we will have
+ // already performed the checking in CheckCompletedCXXClass. Such a
+ // declaration doesn't trigger an implicit definition.
if (Primary == Primary->getCanonicalDecl())
return;
CheckExplicitlyDefaultedSpecialMember(MD);
+ // The exception specification is needed because we are defining the
+ // function.
+ ResolveExceptionSpec(DefaultLoc,
+ MD->getType()->castAs<FunctionProtoType>());
+
switch (Member) {
case CXXDefaultConstructor: {
CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
@@ -10683,6 +11125,40 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
}
}
+bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old) {
+ const FunctionType *NewFT = New->getType()->getAs<FunctionType>();
+ const FunctionType *OldFT = Old->getType()->getAs<FunctionType>();
+
+ CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv();
+
+ // If the calling conventions match, everything is fine
+ if (NewCC == OldCC)
+ return false;
+
+ // If either of the calling conventions are set to "default", we need to pick
+ // something more sensible based on the target. This supports code where the
+ // one method explicitly sets thiscall, and another has no explicit calling
+ // convention.
+ CallingConv Default =
+ Context.getTargetInfo().getDefaultCallingConv(TargetInfo::CCMT_Member);
+ if (NewCC == CC_Default)
+ NewCC = Default;
+ if (OldCC == CC_Default)
+ OldCC = Default;
+
+ // If the calling conventions still don't match, then report the error
+ if (NewCC != OldCC) {
+ Diag(New->getLocation(),
+ diag::err_conflicting_overriding_cc_attributes)
+ << New->getDeclName() << New->getType() << Old->getType();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
+ }
+
+ return false;
+}
+
bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType();
@@ -10949,7 +11425,7 @@ bool Sema::DefineUsedVTables() {
// If this class has a key function, but that key function is
// defined in another translation unit, we don't need to emit the
// vtable even though we're using it.
- const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class);
+ const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class);
if (KeyFunction && !KeyFunction->hasBody()) {
switch (KeyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
@@ -11006,7 +11482,7 @@ bool Sema::DefineUsedVTables() {
Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
// Optionally warn if we're emitting a weak vtable.
- if (Class->getLinkage() == ExternalLinkage &&
+ if (Class->hasExternalLinkage() &&
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
const FunctionDecl *KeyFunctionDef = 0;
if (!KeyFunction ||
@@ -11228,7 +11704,7 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
return false;
TypeLoc TL = TSInfo->getTypeLoc();
- FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>();
if (!ProtoTL)
return false;
@@ -11239,12 +11715,12 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
// within a static member function as they are within a non-static member
// function). [ Note: this is because declaration matching does not occur
// until the complete declarator is known. - end note ]
- const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+ const FunctionProtoType *Proto = ProtoTL.getTypePtr();
FindCXXThisExpr Finder(*this);
// If the return type came after the cv-qualifier-seq, check it now.
if (Proto->hasTrailingReturn() &&
- !Finder.TraverseTypeLoc(ProtoTL->getResultLoc()))
+ !Finder.TraverseTypeLoc(ProtoTL.getResultLoc()))
return true;
// Check the exception specification.
@@ -11260,11 +11736,11 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
return false;
TypeLoc TL = TSInfo->getTypeLoc();
- FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>();
if (!ProtoTL)
return false;
- const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+ const FunctionProtoType *Proto = ProtoTL.getTypePtr();
FindCXXThisExpr Finder(*this);
switch (Proto->getExceptionSpecType()) {
@@ -11354,7 +11830,7 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
ArrayRef<ParsedType> DynamicExceptions,
ArrayRef<SourceRange> DynamicExceptionRanges,
Expr *NoexceptExpr,
- llvm::SmallVectorImpl<QualType> &Exceptions,
+ SmallVectorImpl<QualType> &Exceptions,
FunctionProtoType::ExtProtoInfo &EPI) {
Exceptions.clear();
EPI.ExceptionSpecType = EST;
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index c4e91e85015f..5c26d7ff8e03 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -12,19 +12,19 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/ExternalSemaSource.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprObjC.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclObjC.h"
#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Sema/DeclSpec.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/DenseSet.h"
using namespace clang;
@@ -109,8 +109,7 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
}
void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
- const ObjCMethodDecl *Overridden,
- bool IsImplementation) {
+ const ObjCMethodDecl *Overridden) {
if (Overridden->hasRelatedResultType() &&
!NewMethod->hasRelatedResultType()) {
// This can only happen when the method follows a naming convention that
@@ -152,7 +151,8 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
if (ObjCMethodFamily Family = Overridden->getMethodFamily())
Diag(Overridden->getLocation(),
- diag::note_related_result_type_overridden_family)
+ diag::note_related_result_type_family)
+ << /*overridden method*/ 0
<< Family;
else
Diag(Overridden->getLocation(),
@@ -193,7 +193,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
/// \brief Check a method declaration for compatibility with the Objective-C
/// ARC conventions.
-static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
+bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
ObjCMethodFamily family = method->getMethodFamily();
switch (family) {
case OMF_None:
@@ -207,17 +207,17 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
return false;
case OMF_dealloc:
- if (!S.Context.hasSameType(method->getResultType(), S.Context.VoidTy)) {
+ if (!Context.hasSameType(method->getResultType(), Context.VoidTy)) {
SourceRange ResultTypeRange;
if (const TypeSourceInfo *ResultTypeInfo
= method->getResultTypeSourceInfo())
ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
if (ResultTypeRange.isInvalid())
- S.Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
<< method->getResultType()
<< FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");
else
- S.Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
<< method->getResultType()
<< FixItHint::CreateReplacement(ResultTypeRange, "void");
return true;
@@ -226,11 +226,11 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
case OMF_init:
// If the method doesn't obey the init rules, don't bother annotating it.
- if (S.checkInitMethod(method, QualType()))
+ if (checkInitMethod(method, QualType()))
return true;
- method->addAttr(new (S.Context) NSConsumesSelfAttr(SourceLocation(),
- S.Context));
+ method->addAttr(new (Context) NSConsumesSelfAttr(SourceLocation(),
+ Context));
// Don't add a second copy of this attribute, but otherwise don't
// let it be suppressed.
@@ -249,8 +249,8 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
break;
}
- method->addAttr(new (S.Context) NSReturnsRetainedAttr(SourceLocation(),
- S.Context));
+ method->addAttr(new (Context) NSReturnsRetainedAttr(SourceLocation(),
+ Context));
return false;
}
@@ -373,16 +373,29 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
ObjCMethodDecl *IMD =
IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod());
- if (IMD)
- DiagnoseObjCImplementedDeprecations(*this,
+ if (IMD) {
+ ObjCImplDecl *ImplDeclOfMethodDef =
+ dyn_cast<ObjCImplDecl>(MDecl->getDeclContext());
+ ObjCContainerDecl *ContDeclOfMethodDecl =
+ dyn_cast<ObjCContainerDecl>(IMD->getDeclContext());
+ ObjCImplDecl *ImplDeclOfMethodDecl = 0;
+ if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl))
+ ImplDeclOfMethodDecl = OID->getImplementation();
+ else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl))
+ ImplDeclOfMethodDecl = CD->getImplementation();
+ // No need to issue deprecated warning if deprecated mehod in class/category
+ // is being implemented in its own implementation (no overriding is involved).
+ if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef)
+ DiagnoseObjCImplementedDeprecations(*this,
dyn_cast<NamedDecl>(IMD),
MDecl->getLocation(), 0);
+ }
// If this is "dealloc" or "finalize", set some bit here.
// Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
// Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
// Only do this if the current class actually has a superclass.
- if (IC->getSuperClass()) {
+ if (const ObjCInterfaceDecl *SuperClass = IC->getSuperClass()) {
ObjCMethodFamily Family = MDecl->getMethodFamily();
if (Family == OMF_dealloc) {
if (!(getLangOpts().ObjCAutoRefCount ||
@@ -395,8 +408,8 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
} else {
const ObjCMethodDecl *SuperMethod =
- IC->getSuperClass()->lookupMethod(MDecl->getSelector(),
- MDecl->isInstanceMethod());
+ SuperClass->lookupMethod(MDecl->getSelector(),
+ MDecl->isInstanceMethod());
getCurFunction()->ObjCShouldCallSuper =
(SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());
}
@@ -508,8 +521,14 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType()) {
- if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface())
+ if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+ // This handles the following case:
+ // @interface NewI @end
+ // typedef NewI DeprI __attribute__((deprecated("blah")))
+ // @interface SI : DeprI /* warn here */ @end
+ (void)DiagnoseUseOfDecl(const_cast<TypedefNameDecl*>(TDecl), SuperLoc);
+ }
}
}
@@ -731,7 +750,9 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
// If this is a forward declaration and we are supposed to warn in this
// case, do it.
- if (WarnOnDeclarations && !PDecl->hasDefinition())
+ // FIXME: Recover nicely in the hidden case.
+ if (WarnOnDeclarations &&
+ (!PDecl->hasDefinition() || PDecl->getDefinition()->isHidden()))
Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
<< ProtocolId[i].first;
Protocols.push_back(PDecl);
@@ -837,16 +858,12 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
if (CategoryName) {
/// Check for duplicate interface declaration for this category
- ObjCCategoryDecl *CDeclChain;
- for (CDeclChain = IDecl->getCategoryList(); CDeclChain;
- CDeclChain = CDeclChain->getNextClassCategory()) {
- if (CDeclChain->getIdentifier() == CategoryName) {
- // Class extensions can be declared multiple times.
- Diag(CategoryLoc, diag::warn_dup_category_def)
- << ClassName << CategoryName;
- Diag(CDeclChain->getLocation(), diag::note_previous_definition);
- break;
- }
+ if (ObjCCategoryDecl *Previous
+ = IDecl->FindCategoryDeclaration(CategoryName)) {
+ // Class extensions can be declared multiple times, categories cannot.
+ Diag(CategoryLoc, diag::warn_dup_category_def)
+ << ClassName << CategoryName;
+ Diag(Previous->getLocation(), diag::note_previous_definition);
}
}
@@ -1155,16 +1172,29 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
bool &IncompleteImpl, unsigned DiagID) {
// No point warning no definition of method which is 'unavailable'.
- if (method->hasAttr<UnavailableAttr>())
+ switch (method->getAvailability()) {
+ case AR_Available:
+ case AR_Deprecated:
+ break;
+
+ // Don't warn about unavailable or not-yet-introduced methods.
+ case AR_NotYetIntroduced:
+ case AR_Unavailable:
return;
- if (!IncompleteImpl) {
- Diag(ImpLoc, diag::warn_incomplete_impl);
- IncompleteImpl = true;
}
- if (DiagID == diag::warn_unimplemented_protocol_method)
- Diag(ImpLoc, DiagID) << method->getDeclName();
- else
- Diag(method->getLocation(), DiagID) << method->getDeclName();
+
+ // FIXME: For now ignore 'IncompleteImpl'.
+ // Previously we grouped all unimplemented methods under a single
+ // warning, but some users strongly voiced that they would prefer
+ // separate warnings. We will give that approach a try, as that
+ // matches what we do with protocols.
+
+ Diag(ImpLoc, DiagID) << method->getDeclName();
+
+ // Issue a note to the original declaration.
+ SourceLocation MethodLoc = method->getLocStart();
+ if (MethodLoc.isValid())
+ Diag(MethodLoc, diag::note_method_declared_at) << method;
}
/// Determines if type B can be substituted for type A. Returns true if we can
@@ -1571,6 +1601,11 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy"));
}
+ // If this is a forward protocol declaration, get its definition.
+ if (!PDecl->isThisDeclarationADefinition() &&
+ PDecl->getDefinition())
+ PDecl = PDecl->getDefinition();
+
// If a method lookup fails locally we still need to look and see if
// the method was implemented by a base class or an inherited
// protocol. This lookup is slow, but occurs rarely in correct code
@@ -1603,8 +1638,6 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
if (Diags.getDiagnosticLevel(DIAG, ImpLoc)
!= DiagnosticsEngine::Ignored) {
WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
- Diag(method->getLocation(), diag::note_method_declared_at)
- << method->getDeclName();
Diag(CDecl->getLocation(), diag::note_required_for_protocol_at)
<< PDecl->getDeclName();
}
@@ -1626,8 +1659,6 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
if (Diags.getDiagnosticLevel(DIAG, ImpLoc) !=
DiagnosticsEngine::Ignored) {
WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
- Diag(method->getLocation(), diag::note_method_declared_at)
- << method->getDeclName();
Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) <<
PDecl->getDeclName();
}
@@ -1662,7 +1693,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
!InsMap.count((*I)->getSelector())) {
if (ImmediateClass)
WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
- diag::note_undef_method_impl);
+ diag::warn_undef_method_impl);
continue;
} else {
ObjCMethodDecl *ImpMethodDecl =
@@ -1692,7 +1723,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
if (!ClsMap.count((*I)->getSelector())) {
if (ImmediateClass)
WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
- diag::note_undef_method_impl);
+ diag::warn_undef_method_impl);
} else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getClassMethod((*I)->getSelector());
@@ -1712,24 +1743,27 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
// when checking that methods in implementation match their declaration,
// i.e. when WarnCategoryMethodImpl is false, check declarations in class
// extension; as well as those in categories.
- if (!WarnCategoryMethodImpl)
- for (const ObjCCategoryDecl *CDeclChain = I->getCategoryList();
- CDeclChain; CDeclChain = CDeclChain->getNextClassCategory())
+ if (!WarnCategoryMethodImpl) {
+ for (ObjCInterfaceDecl::visible_categories_iterator
+ Cat = I->visible_categories_begin(),
+ CatEnd = I->visible_categories_end();
+ Cat != CatEnd; ++Cat) {
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl,
- const_cast<ObjCCategoryDecl *>(CDeclChain),
- IncompleteImpl, false,
+ IMPDecl, *Cat, IncompleteImpl, false,
WarnCategoryMethodImpl);
- else
+ }
+ } else {
// Also methods in class extensions need be looked at next.
- for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension();
- ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension())
+ for (ObjCInterfaceDecl::visible_extensions_iterator
+ Ext = I->visible_extensions_begin(),
+ ExtEnd = I->visible_extensions_end();
+ Ext != ExtEnd; ++Ext) {
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl,
- const_cast<ObjCCategoryDecl *>(ClsExtDecl),
- IncompleteImpl, false,
+ IMPDecl, *Ext, IncompleteImpl, false,
WarnCategoryMethodImpl);
-
+ }
+ }
+
// Check for any implementation of a methods declared in protocol.
for (ObjCInterfaceDecl::all_protocol_iterator
PI = I->all_referenced_protocol_begin(),
@@ -1832,11 +1866,12 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
InsMap, ClsMap, I);
// Check class extensions (unnamed categories)
- for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension();
- Categories; Categories = Categories->getNextClassExtension())
- ImplMethodsVsClassMethods(S, IMPDecl,
- const_cast<ObjCCategoryDecl*>(Categories),
- IncompleteImpl);
+ for (ObjCInterfaceDecl::visible_extensions_iterator
+ Ext = I->visible_extensions_begin(),
+ ExtEnd = I->visible_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ 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.
@@ -2017,6 +2052,10 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,
left->getResultType(), right->getResultType()))
return false;
+ // If either is hidden, it is not considered to match.
+ if (left->isHidden() || right->isHidden())
+ return false;
+
if (getLangOpts().ObjCAutoRefCount &&
(left->hasAttr<NSReturnsRetainedAttr>()
!= right->hasAttr<NSReturnsRetainedAttr>() ||
@@ -2141,61 +2180,79 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
if (Pos == MethodPool.end())
return 0;
+ // Gather the non-hidden methods.
ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+ llvm::SmallVector<ObjCMethodDecl *, 4> Methods;
+ for (ObjCMethodList *M = &MethList; M; M = M->Next) {
+ if (M->Method && !M->Method->isHidden()) {
+ // If we're not supposed to warn about mismatches, we're done.
+ if (!warn)
+ return M->Method;
+
+ Methods.push_back(M->Method);
+ }
+ }
- if (warn && MethList.Method && MethList.Next) {
- bool issueDiagnostic = false, issueError = false;
-
- // We support a warning which complains about *any* difference in
- // method signature.
- bool strictSelectorMatch =
- (receiverIdOrClass && warn &&
- (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl,
- R.getBegin()) !=
- DiagnosticsEngine::Ignored));
- if (strictSelectorMatch)
- for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) {
- if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method,
- MMS_strict)) {
- issueDiagnostic = true;
- break;
- }
+ // If there aren't any visible methods, we're done.
+ // FIXME: Recover if there are any known-but-hidden methods?
+ if (Methods.empty())
+ return 0;
+
+ if (Methods.size() == 1)
+ return Methods[0];
+
+ // We found multiple methods, so we may have to complain.
+ bool issueDiagnostic = false, issueError = false;
+
+ // We support a warning which complains about *any* difference in
+ // method signature.
+ bool strictSelectorMatch =
+ (receiverIdOrClass && warn &&
+ (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl,
+ R.getBegin())
+ != DiagnosticsEngine::Ignored));
+ if (strictSelectorMatch) {
+ for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
+ if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) {
+ issueDiagnostic = true;
+ break;
}
+ }
+ }
- // If we didn't see any strict differences, we won't see any loose
- // differences. In ARC, however, we also need to check for loose
- // mismatches, because most of them are errors.
- if (!strictSelectorMatch ||
- (issueDiagnostic && getLangOpts().ObjCAutoRefCount))
- for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) {
- // This checks if the methods differ in type mismatch.
- if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method,
- MMS_loose) &&
- !isAcceptableMethodMismatch(MethList.Method, Next->Method)) {
- issueDiagnostic = true;
- if (getLangOpts().ObjCAutoRefCount)
- issueError = true;
- break;
- }
+ // If we didn't see any strict differences, we won't see any loose
+ // differences. In ARC, however, we also need to check for loose
+ // mismatches, because most of them are errors.
+ if (!strictSelectorMatch ||
+ (issueDiagnostic && getLangOpts().ObjCAutoRefCount))
+ for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
+ // This checks if the methods differ in type mismatch.
+ if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_loose) &&
+ !isAcceptableMethodMismatch(Methods[0], Methods[I])) {
+ issueDiagnostic = true;
+ if (getLangOpts().ObjCAutoRefCount)
+ issueError = true;
+ break;
}
+ }
- if (issueDiagnostic) {
- if (issueError)
- Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;
- else if (strictSelectorMatch)
- Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
- else
- Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
+ if (issueDiagnostic) {
+ if (issueError)
+ Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;
+ else if (strictSelectorMatch)
+ Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
+ else
+ Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
- Diag(MethList.Method->getLocStart(),
- issueError ? diag::note_possibility : diag::note_using)
- << MethList.Method->getSourceRange();
- for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
- Diag(Next->Method->getLocStart(), diag::note_also_found)
- << Next->Method->getSourceRange();
- }
+ Diag(Methods[0]->getLocStart(),
+ issueError ? diag::note_possibility : diag::note_using)
+ << Methods[0]->getSourceRange();
+ for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
+ Diag(Methods[I]->getLocStart(), diag::note_also_found)
+ << Methods[I]->getSourceRange();
}
- return MethList.Method;
+ }
+ return Methods[0];
}
ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
@@ -2334,18 +2391,13 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
}
}
}
- if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
- // Compares properties declared in this class to those of its
- // super class.
- ComparePropertiesInBaseAndSuper(I);
- CompareProperties(I, I);
+ if (isa<ObjCInterfaceDecl>(ClassDecl)) {
+ // Nothing to do here.
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
// Categories are used to extend the class by declaring new methods.
// By the same token, they are also used to add new properties. No
// need to compare the added property to those in the class.
- // Compare protocol properties with those in category
- CompareProperties(C, C);
if (C->IsClassExtension()) {
ObjCInterfaceDecl *CCPrimary = C->getClassInterface();
DiagnoseClassExtensionDupMethods(C, CCPrimary);
@@ -2370,11 +2422,12 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
// of the other class extensions. Mark them as synthesized as
// property will be synthesized when property with same name is
// seen in the @implementation.
- for (const ObjCCategoryDecl *ClsExtDecl =
- IDecl->getFirstClassExtension();
- ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
- for (ObjCContainerDecl::prop_iterator I = ClsExtDecl->prop_begin(),
- E = ClsExtDecl->prop_end(); I != E; ++I) {
+ for (ObjCInterfaceDecl::visible_extensions_iterator
+ Ext = IDecl->visible_extensions_begin(),
+ ExtEnd = IDecl->visible_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ for (ObjCContainerDecl::prop_iterator I = Ext->prop_begin(),
+ E = Ext->prop_end(); I != E; ++I) {
ObjCPropertyDecl *Property = *I;
// Skip over properties declared @dynamic
if (const ObjCPropertyImplDecl *PIDecl
@@ -2382,18 +2435,19 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
if (PIDecl->getPropertyImplementation()
== ObjCPropertyImplDecl::Dynamic)
continue;
-
- for (const ObjCCategoryDecl *CExtDecl =
- IDecl->getFirstClassExtension();
- CExtDecl; CExtDecl = CExtDecl->getNextClassExtension()) {
- if (ObjCMethodDecl *GetterMethod =
- CExtDecl->getInstanceMethod(Property->getGetterName()))
+
+ for (ObjCInterfaceDecl::visible_extensions_iterator
+ Ext = IDecl->visible_extensions_begin(),
+ ExtEnd = IDecl->visible_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ if (ObjCMethodDecl *GetterMethod
+ = Ext->getInstanceMethod(Property->getGetterName()))
GetterMethod->setPropertyAccessor(true);
if (!Property->isReadOnly())
- if (ObjCMethodDecl *SetterMethod =
- CExtDecl->getInstanceMethod(Property->getSetterName()))
+ if (ObjCMethodDecl *SetterMethod
+ = Ext->getInstanceMethod(Property->getSetterName()))
SetterMethod->setPropertyAccessor(true);
- }
+ }
}
}
ImplMethodsVsClassMethods(S, IC, IDecl);
@@ -2442,12 +2496,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
// Find category interface decl and then check that all methods declared
// in this interface are implemented in the category @implementation.
if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) {
- for (ObjCCategoryDecl *Categories = IDecl->getCategoryList();
- Categories; Categories = Categories->getNextClassCategory()) {
- if (Categories->getIdentifier() == CatImplClass->getIdentifier()) {
- ImplMethodsVsClassMethods(S, CatImplClass, Categories);
- break;
- }
+ if (ObjCCategoryDecl *Cat
+ = IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier())) {
+ ImplMethodsVsClassMethods(S, CatImplClass, Cat);
}
}
}
@@ -2682,9 +2733,12 @@ private:
return;
// - categories,
- for (ObjCCategoryDecl *category = iface->getCategoryList();
- category; category = category->getNextClassCategory())
- search(category);
+ for (ObjCInterfaceDecl::known_categories_iterator
+ cat = iface->known_categories_begin(),
+ catEnd = iface->known_categories_end();
+ cat != catEnd; ++cat) {
+ search(*cat);
+ }
// - the super class, and
if (ObjCInterfaceDecl *super = iface->getSuperClass())
@@ -2711,7 +2765,8 @@ private:
void search(ObjCContainerDecl *container) {
// Check for a method in this container which matches this selector.
ObjCMethodDecl *meth = container->getMethod(Method->getSelector(),
- Method->isInstanceMethod());
+ Method->isInstanceMethod(),
+ /*AllowHidden=*/true);
// If we find one, record it and bail out.
if (meth) {
@@ -2858,8 +2913,6 @@ Decl *Sema::ActOnMethodDeclaration(
DI = 0;
} else {
ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
- // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
- ArgType = Context.getAdjustedParameterType(ArgType);
}
LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc,
@@ -2883,7 +2936,7 @@ Decl *Sema::ActOnMethodDeclaration(
ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc,
ArgInfo[i].NameLoc, ArgInfo[i].Name,
- ArgType, DI, SC_None, SC_None);
+ ArgType, DI, SC_None);
Param->setObjCMethodScopeInfo(i);
@@ -2985,7 +3038,7 @@ Decl *Sema::ActOnMethodDeclaration(
bool ARCError = false;
if (getLangOpts().ObjCAutoRefCount)
- ARCError = CheckARCMethodDecl(*this, ObjCMethod);
+ ARCError = CheckARCMethodDecl(ObjCMethod);
// Infer the related result type when possible.
if (!ARCError && RTC == Sema::RTC_Compatible &&
@@ -3114,7 +3167,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
}
VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id,
- T, TInfo, SC_None, SC_None);
+ T, TInfo, SC_None);
New->setExceptionVariable(true);
// In ARC, infer 'retaining' for variables of retainable type.
@@ -3142,7 +3195,7 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
D.getMutableDeclSpec().ClearStorageClassSpecs();
- DiagnoseFunctionSpecifiers(D);
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
// Check that there are no default arguments inside the type of this
// exception object (C++ only).
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index e1f4888d632f..26c3d354c7af 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -16,9 +16,9 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -38,43 +38,55 @@ static const FunctionProtoType *GetUnderlyingFunction(QualType T)
/// CheckSpecifiedExceptionType - Check if the given type is valid in an
/// exception specification. Incomplete types, or pointers to incomplete types
/// other than void are not allowed.
-bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
-
- // This check (and the similar one below) deals with issue 437, that changes
- // C++ 9.2p2 this way:
- // Within the class member-specification, the class is regarded as complete
- // within function bodies, default arguments, exception-specifications, and
- // constructor ctor-initializers (including such things in nested classes).
- if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
- return false;
-
- // C++ 15.4p2: A type denoted in an exception-specification shall not denote
- // an incomplete type.
- if (RequireCompleteType(Range.getBegin(), T,
- diag::err_incomplete_in_exception_spec,
- /*direct*/0, Range))
- return true;
-
- // C++ 15.4p2: A type denoted in an exception-specification shall not denote
- // an incomplete type a pointer or reference to an incomplete type, other
- // than (cv) void*.
- int kind;
- if (const PointerType* IT = T->getAs<PointerType>()) {
- T = IT->getPointeeType();
- kind = 1;
- } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) {
- T = IT->getPointeeType();
- kind = 2;
- } else
- return false;
+///
+/// \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) {
+ // 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
+ // "pointer to function returning T", respectively.
+ //
+ // We also apply this rule in C++98.
+ if (T->isArrayType())
+ T = Context.getArrayDecayedType(T);
+ else if (T->isFunctionType())
+ T = Context.getPointerType(T);
+
+ int Kind = 0;
+ QualType PointeeT = T;
+ if (const PointerType *PT = T->getAs<PointerType>()) {
+ PointeeT = PT->getPointeeType();
+ Kind = 1;
+
+ // cv void* is explicitly permitted, despite being a pointer to an
+ // incomplete type.
+ if (PointeeT->isVoidType())
+ return false;
+ } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
+ PointeeT = RT->getPointeeType();
+ Kind = 2;
+
+ if (RT->isRValueReferenceType()) {
+ // C++11 [except.spec]p2:
+ // A type denoted in an exception-specification shall not denote [...]
+ // an rvalue reference type.
+ Diag(Range.getBegin(), diag::err_rref_in_exception_spec)
+ << T << Range;
+ return true;
+ }
+ }
- // Again as before
- if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
- return false;
-
- if (!T->isVoidType() &&
- RequireCompleteType(Range.getBegin(), T,
- diag::err_incomplete_in_exception_spec, kind, Range))
+ // C++11 [except.spec]p2:
+ // A type denoted in an exception-specification shall not denote an
+ // incomplete type other than a class currently being defined [...].
+ // A type denoted in an exception-specification shall not denote a
+ // pointer or reference to an incomplete type, other than (cv) void* or a
+ // pointer or reference to a class currently being defined.
+ if (!(PointeeT->isRecordType() &&
+ PointeeT->getAs<RecordType>()->isBeingDefined()) &&
+ RequireCompleteType(Range.getBegin(), PointeeT,
+ diag::err_incomplete_in_exception_spec, Kind, Range))
return true;
return false;
@@ -112,7 +124,7 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
return SourceFPT;
// Compute or instantiate the exception specification now.
- if (FPT->getExceptionSpecType() == EST_Unevaluated)
+ if (SourceFPT->getExceptionSpecType() == EST_Unevaluated)
EvaluateImplicitExceptionSpec(Loc, cast<CXXMethodDecl>(SourceDecl));
else
InstantiateExceptionSpec(Loc, SourceDecl);
@@ -159,7 +171,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// If a declaration of a function has an implicit
// exception-specification, other declarations of the function shall
// not specify an exception-specification.
- if (getLangOpts().CPlusPlus0x &&
+ if (getLangOpts().CPlusPlus11 &&
hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) {
Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch)
<< hasImplicitExceptionSpec(Old);
@@ -191,10 +203,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
Old->isExternC()) {
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
EPI.ExceptionSpecType = EST_DynamicNone;
- QualType NewType = Context.getFunctionType(NewProto->getResultType(),
- NewProto->arg_type_begin(),
- NewProto->getNumArgs(),
- EPI);
+ QualType NewType =
+ Context.getFunctionType(NewProto->getResultType(),
+ ArrayRef<QualType>(NewProto->arg_type_begin(),
+ NewProto->getNumArgs()),
+ EPI);
New->setType(NewType);
return false;
}
@@ -215,10 +228,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// Update the type of the function with the appropriate exception
// specification.
- QualType NewType = Context.getFunctionType(NewProto->getResultType(),
- NewProto->arg_type_begin(),
- NewProto->getNumArgs(),
- EPI);
+ QualType NewType =
+ Context.getFunctionType(NewProto->getResultType(),
+ ArrayRef<QualType>(NewProto->arg_type_begin(),
+ NewProto->getNumArgs()),
+ EPI);
New->setType(NewType);
// If exceptions are disabled, suppress the warning about missing
@@ -282,8 +296,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
SourceLocation FixItLoc;
if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
- if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL))
- FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd());
+ if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
+ FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd());
}
if (FixItLoc.isInvalid())
@@ -442,7 +456,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// As a special compatibility feature, under C++0x we accept no spec and
// throw(std::bad_alloc) as equivalent for operator new and operator new[].
// This is because the implicit declaration changed, but old code would break.
- if (getLangOpts().CPlusPlus0x && IsOperatorNew) {
+ if (getLangOpts().CPlusPlus11 && IsOperatorNew) {
const FunctionProtoType *WithExceptions = 0;
if (OldEST == EST_None && NewEST == EST_Dynamic)
WithExceptions = New;
@@ -773,7 +787,7 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
- if (getLangOpts().CPlusPlus0x && isa<CXXDestructorDecl>(New)) {
+ if (getLangOpts().CPlusPlus11 && isa<CXXDestructorDecl>(New)) {
// Don't check uninstantiated template destructors at all. We can only
// synthesize correct specs after the template is instantiated.
if (New->getParent()->isDependentType())
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index bf4abfcb7460..76330f5cdbdd 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -12,13 +12,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/DelayedDiagnostic.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/AnalysisBasedWarnings.h"
-#include "clang/AST/ASTContext.h"
+#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -34,14 +30,17 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Designator.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/SemaFixItUtils.h"
#include "clang/Sema/Template.h"
-#include "TreeTransform.h"
using namespace clang;
using namespace sema;
@@ -163,7 +162,7 @@ static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
for (FunctionDecl::redecl_iterator I = D->redecls_begin(),
E = D->redecls_end();
I != E; ++I) {
- if (I->getStorageClassAsWritten() != SC_None)
+ if (I->getStorageClass() != SC_None)
return true;
}
return false;
@@ -215,19 +214,24 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
: diag::warn_internal_in_extern_inline)
<< /*IsVar=*/!UsedFn << D;
- // Suggest "static" on the inline function, if possible.
- if (!hasAnyExplicitStorageClass(Current)) {
- const FunctionDecl *FirstDecl = Current->getCanonicalDecl();
- SourceLocation DeclBegin = FirstDecl->getSourceRange().getBegin();
- S.Diag(DeclBegin, diag::note_convert_inline_to_static)
- << Current << FixItHint::CreateInsertion(DeclBegin, "static ");
- }
+ S.MaybeSuggestAddingStaticToDecl(Current);
S.Diag(D->getCanonicalDecl()->getLocation(),
diag::note_internal_decl_declared_here)
<< D;
}
+void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
+ const FunctionDecl *First = Cur->getFirstDeclaration();
+
+ // Suggest "static" on the function, if possible.
+ if (!hasAnyExplicitStorageClass(First)) {
+ SourceLocation DeclBegin = First->getSourceRange().getBegin();
+ Diag(DeclBegin, diag::note_convert_inline_to_static)
+ << Cur << FixItHint::CreateInsertion(DeclBegin, "static ");
+ }
+}
+
/// \brief Determine whether the use of this declaration is valid, and
/// emit any corresponding diagnostics.
///
@@ -288,12 +292,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
/// diagnostic complaining about the given function being deleted or
/// unavailable.
std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
- // FIXME: C++0x implicitly-deleted special member functions could be
- // detected here so that we could improve diagnostics to say, e.g.,
- // "base class 'A' had a deleted copy constructor".
- if (FD->isDeleted())
- return std::string();
-
std::string Message;
if (FD->getAvailability(&Message))
return ": " + Message;
@@ -457,6 +455,62 @@ static void CheckForNullPointerDereference(Sema &S, Expr *E) {
}
}
+static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
+ SourceLocation AssignLoc,
+ const Expr* RHS) {
+ const ObjCIvarDecl *IV = OIRE->getDecl();
+ if (!IV)
+ return;
+
+ DeclarationName MemberName = IV->getDeclName();
+ IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+ if (!Member || !Member->isStr("isa"))
+ return;
+
+ const Expr *Base = OIRE->getBase();
+ QualType BaseType = Base->getType();
+ if (OIRE->isArrow())
+ BaseType = BaseType->getPointeeType();
+ if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>())
+ if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) {
+ ObjCInterfaceDecl *ClassDeclared = 0;
+ ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
+ if (!ClassDeclared->getSuperClass()
+ && (*ClassDeclared->ivar_begin()) == IV) {
+ if (RHS) {
+ NamedDecl *ObjectSetClass =
+ S.LookupSingleName(S.TUScope,
+ &S.Context.Idents.get("object_setClass"),
+ SourceLocation(), S.LookupOrdinaryName);
+ if (ObjectSetClass) {
+ SourceLocation RHSLocEnd = S.PP.getLocForEndOfToken(RHS->getLocEnd());
+ S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign) <<
+ FixItHint::CreateInsertion(OIRE->getLocStart(), "object_setClass(") <<
+ FixItHint::CreateReplacement(SourceRange(OIRE->getOpLoc(),
+ AssignLoc), ",") <<
+ FixItHint::CreateInsertion(RHSLocEnd, ")");
+ }
+ else
+ S.Diag(OIRE->getLocation(), diag::warn_objc_isa_assign);
+ } else {
+ NamedDecl *ObjectGetClass =
+ S.LookupSingleName(S.TUScope,
+ &S.Context.Idents.get("object_getClass"),
+ SourceLocation(), S.LookupOrdinaryName);
+ if (ObjectGetClass)
+ S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use) <<
+ FixItHint::CreateInsertion(OIRE->getLocStart(), "object_getClass(") <<
+ FixItHint::CreateReplacement(
+ SourceRange(OIRE->getOpLoc(),
+ OIRE->getLocEnd()), ")");
+ else
+ S.Diag(OIRE->getLocation(), diag::warn_objc_isa_use);
+ }
+ S.Diag(IV->getLocation(), diag::note_ivar_decl);
+ }
+ }
+}
+
ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
@@ -489,8 +543,31 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (T->isVoidType())
return Owned(E);
- CheckForNullPointerDereference(*this, E);
+ // OpenCL usually rejects direct accesses to values of 'half' type.
+ if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
+ T->isHalfType()) {
+ Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
+ << 0 << T;
+ return ExprError();
+ }
+ CheckForNullPointerDereference(*this, E);
+ if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(E->IgnoreParenCasts())) {
+ NamedDecl *ObjectGetClass = LookupSingleName(TUScope,
+ &Context.Idents.get("object_getClass"),
+ SourceLocation(), LookupOrdinaryName);
+ if (ObjectGetClass)
+ Diag(E->getExprLoc(), diag::warn_objc_isa_use) <<
+ FixItHint::CreateInsertion(OISA->getLocStart(), "object_getClass(") <<
+ FixItHint::CreateReplacement(
+ SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")");
+ else
+ Diag(E->getExprLoc(), diag::warn_objc_isa_use);
+ }
+ else if (const ObjCIvarRefExpr *OIRE =
+ dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
+ DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/0);
+
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
// cv-unqualified version of T. Otherwise, the type of the
@@ -504,6 +581,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
T = T.getUnqualifiedType();
UpdateMarkingForLValueToRValue(E);
+
+ // Loading a __weak object implicitly retains the value, so we need a cleanup to
+ // balance that.
+ if (getLangOpts().ObjCAutoRefCount &&
+ E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
+ ExprNeedsCleanups = true;
ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
E, 0, VK_RValue));
@@ -540,15 +623,14 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) {
// First, convert to an r-value.
ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
if (Res.isInvalid())
- return Owned(E);
+ return ExprError();
E = Res.take();
QualType Ty = E->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
- // Half FP is a bit different: it's a storage-only type, meaning that any
- // "use" of it should be promoted to float.
- if (Ty->isHalfType())
+ // Half FP have to be promoted to float unless it is natively supported
+ if (Ty->isHalfType() && !getLangOpts().NativeHalfType)
return ImpCastExprToType(Res.take(), Context.FloatTy, CK_FloatingCast);
// Try to perform integral promotions if the object has a theoretically
@@ -583,19 +665,23 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) {
}
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
-/// do not have a prototype. Arguments that have type float are promoted to
-/// double. All other argument types are converted by UsualUnaryConversions().
+/// do not have a prototype. Arguments that have type float or __fp16
+/// are promoted to double. All other argument types are converted by
+/// UsualUnaryConversions().
ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
ExprResult Res = UsualUnaryConversions(E);
if (Res.isInvalid())
- return Owned(E);
+ return ExprError();
E = Res.take();
- // If this is a 'float' (CVR qualified or typedef) promote to double.
- if (Ty->isSpecificBuiltinType(BuiltinType::Float))
+ // If this is a 'float' or '__fp16' (CVR qualified or typedef) promote to
+ // double.
+ const BuiltinType *BTy = Ty->getAs<BuiltinType>();
+ if (BTy && (BTy->getKind() == BuiltinType::Half ||
+ BTy->getKind() == BuiltinType::Float))
E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take();
// C++ performs lvalue-to-rvalue conversion as a default argument
@@ -635,16 +721,16 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
if (Ty.isCXX98PODType(Context))
return VAK_Valid;
- // C++0x [expr.call]p7:
- // Passing a potentially-evaluated argument of class type (Clause 9)
+ // C++11 [expr.call]p7:
+ // Passing a potentially-evaluated argument of class type (Clause 9)
// having a non-trivial copy constructor, a non-trivial move constructor,
- // or a non-trivial destructor, with no corresponding parameter,
+ // or a non-trivial destructor, with no corresponding parameter,
// is conditionally-supported with implementation-defined semantics.
- if (getLangOpts().CPlusPlus0x && !Ty->isDependentType())
+ if (getLangOpts().CPlusPlus11 && !Ty->isDependentType())
if (CXXRecordDecl *Record = Ty->getAsCXXRecordDecl())
- if (Record->hasTrivialCopyConstructor() &&
- Record->hasTrivialMoveConstructor() &&
- Record->hasTrivialDestructor())
+ if (!Record->hasNonTrivialCopyConstructor() &&
+ !Record->hasNonTrivialMoveConstructor() &&
+ !Record->hasNonTrivialDestructor())
return VAK_ValidInCXX11;
if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType())
@@ -673,7 +759,7 @@ bool Sema::variadicArgumentPODCheck(const Expr *E, VariadicCallType CT) {
return DiagRuntimeBehavior(E->getLocStart(), 0,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
- << getLangOpts().CPlusPlus0x << Ty << CT);
+ << getLangOpts().CPlusPlus11 << Ty << CT);
}
}
// c++ rules are enforced elsewhere.
@@ -938,54 +1024,24 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
/*convertFloat=*/!IsCompAssign);
}
-/// \brief Handle conversions with GCC complex int extension. Helper function
-/// of UsualArithmeticConversions()
-// FIXME: if the operands are (int, _Complex long), we currently
-// don't promote the complex. Also, signedness?
-static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
- ExprResult &RHS, QualType LHSType,
- QualType RHSType,
- bool IsCompAssign) {
- const ComplexType *LHSComplexInt = LHSType->getAsComplexIntegerType();
- const ComplexType *RHSComplexInt = RHSType->getAsComplexIntegerType();
+typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType);
- if (LHSComplexInt && RHSComplexInt) {
- int order = S.Context.getIntegerTypeOrder(LHSComplexInt->getElementType(),
- RHSComplexInt->getElementType());
- assert(order && "inequal types with equal element ordering");
- if (order > 0) {
- // _Complex int -> _Complex long
- RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralComplexCast);
- return LHSType;
- }
-
- if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralComplexCast);
- return RHSType;
- }
-
- if (LHSComplexInt) {
- // int -> _Complex int
- // FIXME: This needs to take integer ranks into account
- RHS = S.ImpCastExprToType(RHS.take(), LHSComplexInt->getElementType(),
- CK_IntegralCast);
- RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralRealToComplex);
- return LHSType;
- }
+namespace {
+/// These helper callbacks are placed in an anonymous namespace to
+/// permit their use as function template parameters.
+ExprResult doIntegralCast(Sema &S, Expr *op, QualType toType) {
+ return S.ImpCastExprToType(op, toType, CK_IntegralCast);
+}
- assert(RHSComplexInt);
- // int -> _Complex int
- // FIXME: This needs to take integer ranks into account
- if (!IsCompAssign) {
- LHS = S.ImpCastExprToType(LHS.take(), RHSComplexInt->getElementType(),
- CK_IntegralCast);
- LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralRealToComplex);
- }
- return RHSType;
+ExprResult doComplexIntegralCast(Sema &S, Expr *op, QualType toType) {
+ return S.ImpCastExprToType(op, S.Context.getComplexType(toType),
+ CK_IntegralComplexCast);
+}
}
/// \brief Handle integer arithmetic conversions. Helper function of
/// UsualArithmeticConversions()
+template <PerformCastFn doLHSCast, PerformCastFn doRHSCast>
static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType, bool IsCompAssign) {
@@ -996,29 +1052,29 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
if (LHSSigned == RHSSigned) {
// Same signedness; use the higher-ranked type
if (order >= 0) {
- RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast);
+ RHS = (*doRHSCast)(S, RHS.take(), LHSType);
return LHSType;
} else if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast);
+ LHS = (*doLHSCast)(S, LHS.take(), RHSType);
return RHSType;
} else if (order != (LHSSigned ? 1 : -1)) {
// The unsigned type has greater than or equal rank to the
// signed type, so use the unsigned type
if (RHSSigned) {
- RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast);
+ RHS = (*doRHSCast)(S, RHS.take(), LHSType);
return LHSType;
} else if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast);
+ LHS = (*doLHSCast)(S, LHS.take(), RHSType);
return RHSType;
} else if (S.Context.getIntWidth(LHSType) != S.Context.getIntWidth(RHSType)) {
// The two types are different widths; if we are here, that
// means the signed type is larger than the unsigned type, so
// use the signed type.
if (LHSSigned) {
- RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast);
+ RHS = (*doRHSCast)(S, RHS.take(), LHSType);
return LHSType;
} else if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast);
+ LHS = (*doLHSCast)(S, LHS.take(), RHSType);
return RHSType;
} else {
// The signed type is higher-ranked than the unsigned type,
@@ -1027,19 +1083,62 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
// to the signed type.
QualType result =
S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType);
- RHS = S.ImpCastExprToType(RHS.take(), result, CK_IntegralCast);
+ RHS = (*doRHSCast)(S, RHS.take(), result);
if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.take(), result, CK_IntegralCast);
+ LHS = (*doLHSCast)(S, LHS.take(), result);
return result;
}
}
+/// \brief Handle conversions with GCC complex int extension. Helper function
+/// of UsualArithmeticConversions()
+static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
+ ExprResult &RHS, QualType LHSType,
+ QualType RHSType,
+ bool IsCompAssign) {
+ const ComplexType *LHSComplexInt = LHSType->getAsComplexIntegerType();
+ const ComplexType *RHSComplexInt = RHSType->getAsComplexIntegerType();
+
+ if (LHSComplexInt && RHSComplexInt) {
+ QualType LHSEltType = LHSComplexInt->getElementType();
+ QualType RHSEltType = RHSComplexInt->getElementType();
+ QualType ScalarType =
+ handleIntegerConversion<doComplexIntegralCast, doComplexIntegralCast>
+ (S, LHS, RHS, LHSEltType, RHSEltType, IsCompAssign);
+
+ return S.Context.getComplexType(ScalarType);
+ }
+
+ if (LHSComplexInt) {
+ QualType LHSEltType = LHSComplexInt->getElementType();
+ QualType ScalarType =
+ handleIntegerConversion<doComplexIntegralCast, doIntegralCast>
+ (S, LHS, RHS, LHSEltType, RHSType, IsCompAssign);
+ QualType ComplexType = S.Context.getComplexType(ScalarType);
+ RHS = S.ImpCastExprToType(RHS.take(), ComplexType,
+ CK_IntegralRealToComplex);
+
+ return ComplexType;
+ }
+
+ assert(RHSComplexInt);
+
+ QualType RHSEltType = RHSComplexInt->getElementType();
+ QualType ScalarType =
+ handleIntegerConversion<doIntegralCast, doComplexIntegralCast>
+ (S, LHS, RHS, LHSType, RHSEltType, IsCompAssign);
+ QualType ComplexType = S.Context.getComplexType(ScalarType);
+
+ if (!IsCompAssign)
+ LHS = S.ImpCastExprToType(LHS.take(), ComplexType,
+ CK_IntegralRealToComplex);
+ return ComplexType;
+}
+
/// UsualArithmeticConversions - Performs various conversions that are common to
/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
/// routine returns the first non-arithmetic type found. The client is
/// responsible for emitting appropriate error diagnostics.
-/// FIXME: verify the conversion rules for "complex int" are consistent with
-/// GCC.
QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
bool IsCompAssign) {
if (!IsCompAssign) {
@@ -1104,10 +1203,11 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
IsCompAssign);
// Finally, we have two differing integer types.
- return handleIntegerConversion(*this, LHS, RHS, LHSType, RHSType,
- IsCompAssign);
+ return handleIntegerConversion<doIntegralCast, doIntegralCast>
+ (*this, LHS, RHS, LHSType, RHSType, IsCompAssign);
}
+
//===----------------------------------------------------------------------===//
// Semantic Analysis for various Expression Types
//===----------------------------------------------------------------------===//
@@ -1149,6 +1249,12 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
TypeSourceInfo **Types,
Expr **Exprs,
unsigned NumAssocs) {
+ if (ControllingExpr->getType()->isPlaceholderType()) {
+ ExprResult result = CheckPlaceholderExpr(ControllingExpr);
+ if (result.isInvalid()) return ExprError();
+ ControllingExpr = result.take();
+ }
+
bool TypeErrorFound = false,
IsResultDependent = ControllingExpr->isTypeDependent(),
ContainsUnexpandedParameterPack
@@ -1401,7 +1507,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
ExprResult
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
- const CXXScopeSpec *SS) {
+ const CXXScopeSpec *SS, NamedDecl *FoundD) {
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) {
@@ -1425,7 +1531,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
: NestedNameSpecifierLoc(),
SourceLocation(),
D, refersToEnclosingScope,
- NameInfo, Ty, VK);
+ NameInfo, Ty, VK, FoundD);
MarkDeclRefReferenced(E);
@@ -1533,9 +1639,10 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(
CallsUndergoingInstantiation.back()->getCallee());
-
CXXMethodDecl *DepMethod;
- if (CurMethod->getTemplatedKind() ==
+ if (CurMethod->isDependentContext())
+ DepMethod = CurMethod;
+ else if (CurMethod->getTemplatedKind() ==
FunctionDecl::TK_FunctionTemplateSpecialization)
DepMethod = cast<CXXMethodDecl>(CurMethod->getPrimaryTemplate()->
getInstantiatedFromMemberTemplate()->getTemplatedDecl());
@@ -1642,9 +1749,13 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
<< SS.getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
- if (ND)
- Diag(ND->getLocation(), diag::note_previous_decl)
- << CorrectedQuotedStr;
+
+ unsigned diag = isa<ImplicitParamDecl>(ND)
+ ? diag::note_implicit_param_decl
+ : diag::note_previous_decl;
+
+ Diag(ND->getLocation(), diag)
+ << CorrectedQuotedStr;
// Tell the callee to try to recover.
return false;
@@ -1946,6 +2057,10 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IdentifierInfo *II, bool AllowBuiltinCreation) {
SourceLocation Loc = Lookup.getNameLoc();
ObjCMethodDecl *CurMethod = getCurMethodDecl();
+
+ // Check for error condition which is already reported.
+ if (!CurMethod)
+ return ExprError();
// There are two cases to handle here. 1) scoped lookup could have failed,
// in which case we should look for an ivar. 2) scoped lookup could have
@@ -2009,14 +2124,15 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
if (SelfExpr.isInvalid())
return ExprError();
- MarkAnyDeclReferenced(Loc, IV);
+ MarkAnyDeclReferenced(Loc, IV, true);
ObjCMethodFamily MF = CurMethod->getMethodFamily();
- if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize)
+ if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
+ !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
- Loc,
+ Loc, IV->getLocation(),
SelfExpr.take(),
true, true);
@@ -2321,8 +2437,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// If this is a single, fully-resolved result and we don't need ADL,
// just build an ordinary singleton decl ref.
if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
- return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(),
- R.getFoundDecl());
+ return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),
+ R.getRepresentativeDecl());
// We only need to check the declaration if there's exactly one
// result, because in the overloaded case the results can only be
@@ -2350,7 +2466,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
ExprResult
Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
- NamedDecl *D) {
+ NamedDecl *D, NamedDecl *FoundD) {
assert(D && "Cannot refer to a NULL declaration");
assert(!isa<FunctionTemplateDecl>(D) &&
"Cannot refer unambiguously to a function template");
@@ -2546,7 +2662,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
break;
}
- return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS);
+ return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD);
}
}
@@ -2565,8 +2681,14 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
// string.
Decl *currentDecl = getCurFunctionOrMethodDecl();
- if (!currentDecl && getCurBlock())
- currentDecl = getCurBlock()->TheDecl;
+ // Blocks and lambdas can occur at global scope. Don't emit a warning.
+ if (!currentDecl) {
+ if (const BlockScopeInfo *BSI = getCurBlock())
+ currentDecl = BSI->TheDecl;
+ else if (const LambdaScopeInfo *LSI = getCurLambda())
+ currentDecl = LSI->CallOperator;
+ }
+
if (!currentDecl) {
Diag(Loc, diag::ext_predef_outside_function);
currentDecl = Context.getTranslationUnitDecl();
@@ -2764,7 +2886,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
SourceLocation TokLoc = Tok.getLocation();
unsigned Length = Literal.getUDSuffixOffset();
QualType StrTy = Context.getConstantArrayType(
- Context.CharTy, llvm::APInt(32, Length + 1),
+ Context.CharTy.withConst(), llvm::APInt(32, Length + 1),
ArrayType::Normal, 0);
Expr *Lit = StringLiteral::Create(
Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii,
@@ -2825,7 +2947,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (!getLangOpts().C99 && Literal.isLongLong) {
if (getLangOpts().CPlusPlus)
Diag(Tok.getLocation(),
- getLangOpts().CPlusPlus0x ?
+ getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
else
Diag(Tok.getLocation(), diag::ext_c99_longlong);
@@ -2835,7 +2957,10 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth();
// The microsoft literal suffix extensions support 128-bit literals, which
// may be wider than [u]intmax_t.
- if (Literal.isMicrosoftInteger && MaxWidth < 128)
+ // FIXME: Actually, they don't. We seem to have accidentally invented the
+ // i128 suffix.
+ if (Literal.isMicrosoftInteger && MaxWidth < 128 &&
+ PP.getTargetInfo().hasInt128Type())
MaxWidth = 128;
llvm::APInt ResultVal(MaxWidth, 0);
@@ -2905,7 +3030,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// If it doesn't fit in unsigned long long, and we're using Microsoft
// extensions, then its a 128-bit integer literal.
- if (Ty.isNull() && Literal.isMicrosoftInteger) {
+ if (Ty.isNull() && Literal.isMicrosoftInteger &&
+ PP.getTargetInfo().hasInt128Type()) {
if (Literal.isUnsigned)
Ty = Context.UnsignedInt128Ty;
else
@@ -2963,16 +3089,17 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
SourceRange ArgRange,
UnaryExprOrTypeTrait TraitKind) {
// C99 6.5.3.4p1:
- if (T->isFunctionType()) {
- // alignof(function) is allowed as an extension.
- if (TraitKind == UETT_SizeOf)
- S.Diag(Loc, diag::ext_sizeof_function_type) << ArgRange;
+ if (T->isFunctionType() &&
+ (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) {
+ // sizeof(function)/alignof(function) is allowed as an extension.
+ S.Diag(Loc, diag::ext_sizeof_alignof_function_type)
+ << TraitKind << ArgRange;
return false;
}
// Allow sizeof(void)/alignof(void) as an extension.
if (T->isVoidType()) {
- S.Diag(Loc, diag::ext_sizeof_void_type) << TraitKind << ArgRange;
+ S.Diag(Loc, diag::ext_sizeof_alignof_void_type) << TraitKind << ArgRange;
return false;
}
@@ -2995,6 +3122,24 @@ static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T,
return false;
}
+/// \brief Check whether E is a pointer from a decayed array type (the decayed
+/// pointer type is equal to T) and emit a warning if it is.
+static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
+ Expr *E) {
+ // Don't warn if the operation changed the type.
+ if (T != E->getType())
+ return;
+
+ // Now look for array decays.
+ ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E);
+ if (!ICE || ICE->getCastKind() != CK_ArrayToPointerDecay)
+ return;
+
+ S.Diag(Loc, diag::warn_sizeof_array_decay) << ICE->getSourceRange()
+ << ICE->getType()
+ << ICE->getSubExpr()->getType();
+}
+
/// \brief Check the constrains on expression operands to unary type expression
/// and type traits.
///
@@ -3048,6 +3193,16 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
}
}
}
+
+ // Warn on "sizeof(array op x)" and "sizeof(x op array)", where the array
+ // decays into a pointer and returns an unintended result. This is most
+ // likely a typo for "sizeof(array) op x".
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E->IgnoreParens())) {
+ warnOnSizeofOnArrayDecay(*this, BO->getOperatorLoc(), BO->getType(),
+ BO->getLHS());
+ warnOnSizeofOnArrayDecay(*this, BO->getOperatorLoc(), BO->getType(),
+ BO->getRHS());
+ }
}
return false;
@@ -3189,7 +3344,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
return ExprError();
if (ExprKind == UETT_SizeOf && E->getType()->isVariableArrayType()) {
- PE = TranformToPotentiallyEvaluated(E);
+ PE = TransformToPotentiallyEvaluated(E);
if (PE.isInvalid()) return ExprError();
E = PE.take();
}
@@ -3292,33 +3447,56 @@ static bool checkArithmeticOnObjCPointer(Sema &S,
}
ExprResult
-Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
- Expr *Idx, SourceLocation RLoc) {
+Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
+ Expr *idx, SourceLocation rbLoc) {
// Since this might be a postfix expression, get rid of ParenListExprs.
- ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
- if (Result.isInvalid()) return ExprError();
- Base = Result.take();
+ if (isa<ParenListExpr>(base)) {
+ ExprResult result = MaybeConvertParenListExprToParenExpr(S, base);
+ if (result.isInvalid()) return ExprError();
+ base = result.take();
+ }
- Expr *LHSExp = Base, *RHSExp = Idx;
+ // Handle any non-overload placeholder types in the base and index
+ // expressions. We can't handle overloads here because the other
+ // operand might be an overloadable type, in which case the overload
+ // resolution for the operator overload should get the first crack
+ // at the overload.
+ if (base->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult result = CheckPlaceholderExpr(base);
+ if (result.isInvalid()) return ExprError();
+ base = result.take();
+ }
+ if (idx->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult result = CheckPlaceholderExpr(idx);
+ if (result.isInvalid()) return ExprError();
+ idx = result.take();
+ }
+ // Build an unanalyzed expression if either operand is type-dependent.
if (getLangOpts().CPlusPlus &&
- (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
- return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
+ (base->isTypeDependent() || idx->isTypeDependent())) {
+ return Owned(new (Context) ArraySubscriptExpr(base, idx,
Context.DependentTy,
VK_LValue, OK_Ordinary,
- RLoc));
+ 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
+ // operators, so there's nothing interesting for overload resolution
+ // to do if there aren't any record types involved.
+ //
+ // ObjC pointers have their own subscripting logic that is not tied
+ // to overload resolution and so should not take this path.
if (getLangOpts().CPlusPlus &&
- (LHSExp->getType()->isRecordType() ||
- LHSExp->getType()->isEnumeralType() ||
- RHSExp->getType()->isRecordType() ||
- RHSExp->getType()->isEnumeralType()) &&
- !LHSExp->getType()->isObjCObjectPointerType()) {
- return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx);
+ (base->getType()->isRecordType() ||
+ (!base->getType()->isObjCObjectPointerType() &&
+ idx->getType()->isRecordType()))) {
+ return CreateOverloadedArraySubscriptExpr(lbLoc, rbLoc, base, idx);
}
- return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc);
+ return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc);
}
ExprResult
@@ -3525,7 +3703,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
return ExprError();
Expr *Arg = Result.takeAs<Expr>();
- CheckImplicitConversions(Arg, Param->getOuterLocStart());
+ CheckCompletedExpr(Arg, Param->getOuterLocStart());
// Build the default argument expression.
return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, Arg));
}
@@ -3687,7 +3865,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
Expr **Args, unsigned NumArgs,
SmallVector<Expr *, 8> &AllArgs,
VariadicCallType CallType,
- bool AllowExplicit) {
+ bool AllowExplicit,
+ bool IsListInitialization) {
unsigned NumArgsInProto = Proto->getNumArgs();
unsigned NumArgsToCheck = NumArgs;
bool Invalid = false;
@@ -3720,20 +3899,21 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
(!Param || !Param->hasAttr<CFConsumedAttr>()))
Arg = stripARCUnbridgedCast(Arg);
- InitializedEntity Entity =
- Param? InitializedEntity::InitializeParameter(Context, Param)
- : InitializedEntity::InitializeParameter(Context, ProtoArgType,
- Proto->isArgConsumed(i));
+ InitializedEntity Entity = Param ?
+ InitializedEntity::InitializeParameter(Context, Param, ProtoArgType)
+ : InitializedEntity::InitializeParameter(Context, ProtoArgType,
+ Proto->isArgConsumed(i));
ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(Arg),
- /*TopLevelOfInitList=*/false,
+ IsListInitialization,
AllowExplicit);
if (ArgE.isInvalid())
return true;
Arg = ArgE.takeAs<Expr>();
} else {
+ assert(FDecl && "can't use default arguments without a known callee");
Param = FDecl->getParamDecl(i);
ExprResult ArgExpr =
@@ -3762,11 +3942,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
if (Proto->getResultType() == Context.UnknownAnyTy &&
FDecl && FDecl->isExternC()) {
for (unsigned i = ArgIx; i != NumArgs; ++i) {
- ExprResult arg;
- if (isa<ExplicitCastExpr>(Args[i]->IgnoreParens()))
- arg = DefaultFunctionArrayLvalueConversion(Args[i]);
- else
- arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
+ QualType paramType; // ignored
+ ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType);
Invalid |= arg.isInvalid();
AllArgs.push_back(arg.take());
}
@@ -3790,9 +3967,9 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc();
- if (ArrayTypeLoc *ATL = dyn_cast<ArrayTypeLoc>(&TL))
+ if (ArrayTypeLoc ATL = TL.getAs<ArrayTypeLoc>())
S.Diag(PVD->getLocation(), diag::note_callee_static_array)
- << ATL->getLocalSourceRange();
+ << ATL.getLocalSourceRange();
}
/// CheckStaticArrayArgument - If the given argument corresponds to a static
@@ -4593,10 +4770,15 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
Expr **exprs;
unsigned numExprs;
Expr *subExpr;
+ SourceLocation LiteralLParenLoc, LiteralRParenLoc;
if (ParenListExpr *PE = dyn_cast<ParenListExpr>(E)) {
+ LiteralLParenLoc = PE->getLParenLoc();
+ LiteralRParenLoc = PE->getRParenLoc();
exprs = PE->getExprs();
numExprs = PE->getNumExprs();
- } else {
+ } else { // isa<ParenExpr> by assertion at function entrance
+ LiteralLParenLoc = cast<ParenExpr>(E)->getLParen();
+ LiteralRParenLoc = cast<ParenExpr>(E)->getRParen();
subExpr = cast<ParenExpr>(E)->getSubExpr();
exprs = &subExpr;
numExprs = 1;
@@ -4653,8 +4835,8 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
}
// FIXME: This means that pretty-printing the final AST will produce curly
// braces instead of the original commas.
- InitListExpr *initE = new (Context) InitListExpr(Context, LParenLoc,
- initExprs, RParenLoc);
+ InitListExpr *initE = new (Context) InitListExpr(Context, LiteralLParenLoc,
+ initExprs, LiteralRParenLoc);
initE->setType(Ty);
return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE);
}
@@ -4681,7 +4863,6 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
ExprResult Sema::ActOnParenListExpr(SourceLocation L,
SourceLocation R,
MultiExprArg Val) {
- assert(Val.data() != 0 && "ActOnParenOrParenListExpr() missing expr list");
Expr *expr = new (Context) ParenListExpr(Context, L, Val, R);
return Owned(expr);
}
@@ -4720,7 +4901,7 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
return false;
}
- int DiagType = (NullKind == Expr::NPCK_CXX0X_nullptr);
+ int DiagType = (NullKind == Expr::NPCK_CXX11_nullptr);
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands_null)
<< NonPointerExpr->getType() << DiagType
<< NonPointerExpr->getSourceRange();
@@ -4734,7 +4915,7 @@ static bool checkCondition(Sema &S, Expr *Cond) {
// C99 6.5.15p2
if (CondTy->isScalarType()) return false;
- // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar.
+ // OpenCL v1.1 s6.3.i says the condition is allowed to be a vector or scalar.
if (S.getLangOpts().OpenCL && CondTy->isVectorType())
return false;
@@ -4995,9 +5176,9 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
if (LHSTy->isVectorType() || RHSTy->isVectorType())
return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
- // OpenCL: If the condition is a vector, and both operands are scalar,
+ // If the condition is a vector, and both operands are scalar,
// attempt to implicity convert them to the vector type to act like the
- // built in select.
+ // built in select. (OpenCL v1.1 s6.3.i)
if (getLangOpts().OpenCL && CondTy->isVectorType())
if (checkConditionalConvertScalarsToVectors(*this, LHS, RHS, CondTy))
return QualType();
@@ -5264,7 +5445,8 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
// Make sure this is really a binary operator that is safe to pass into
// BinaryOperator::getOverloadedOpcode(), e.g. it's not a subscript op.
OverloadedOperatorKind OO = Call->getOperator();
- if (OO < OO_Plus || OO > OO_Arrow)
+ if (OO < OO_Plus || OO > OO_Arrow ||
+ OO == OO_PlusPlus || OO == OO_MinusMinus)
return false;
BinaryOperatorKind OpKind = BinaryOperator::getOverloadedOpcode(OO);
@@ -5625,7 +5807,6 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType();
RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType();
-
// Common case: no conversion required.
if (LHSType == RHSType) {
Kind = CK_NoOp;
@@ -6570,6 +6751,11 @@ static bool isScopedEnumerationType(QualType T) {
static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, unsigned 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.
+ if (S.getLangOpts().OpenCL)
+ return;
+
llvm::APSInt Right;
// Check right/shifter operand
if (RHS.get()->isValueDependent() ||
@@ -6689,10 +6875,10 @@ static bool IsWithinTemplateSpecialization(Decl *D) {
}
/// If two different enums are compared, raise a warning.
-static void checkEnumComparison(Sema &S, SourceLocation Loc, ExprResult &LHS,
- ExprResult &RHS) {
- QualType LHSStrippedType = LHS.get()->IgnoreParenImpCasts()->getType();
- QualType RHSStrippedType = RHS.get()->IgnoreParenImpCasts()->getType();
+static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS,
+ Expr *RHS) {
+ QualType LHSStrippedType = LHS->IgnoreParenImpCasts()->getType();
+ QualType RHSStrippedType = RHS->IgnoreParenImpCasts()->getType();
const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>();
if (!LHSEnumType)
@@ -6712,7 +6898,7 @@ static void checkEnumComparison(Sema &S, SourceLocation Loc, ExprResult &LHS,
S.Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
<< LHSStrippedType << RHSStrippedType
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ << LHS->getSourceRange() << RHS->getSourceRange();
}
/// \brief Diagnose bad pointer comparisons.
@@ -6796,18 +6982,18 @@ static bool isObjCObjectLiteral(ExprResult &E) {
}
static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
- // Get the LHS object's interface type.
- QualType Type = LHS->getType();
- QualType InterfaceType;
- if (const ObjCObjectPointerType *PTy = Type->getAs<ObjCObjectPointerType>()) {
- InterfaceType = PTy->getPointeeType();
- if (const ObjCObjectType *iQFaceTy =
- InterfaceType->getAsObjCQualifiedInterfaceType())
- InterfaceType = iQFaceTy->getBaseType();
- } else {
- // If this is not actually an Objective-C object, bail out.
+ const ObjCObjectPointerType *Type =
+ LHS->getType()->getAs<ObjCObjectPointerType>();
+
+ // If this is not actually an Objective-C object, bail out.
+ if (!Type)
return false;
- }
+
+ // Get the LHS object's interface type.
+ QualType InterfaceType = Type->getPointeeType();
+ if (const ObjCObjectType *iQFaceTy =
+ InterfaceType->getAsObjCQualifiedInterfaceType())
+ InterfaceType = iQFaceTy->getBaseType();
// If the RHS isn't an Objective-C object, bail out.
if (!RHS->getType()->isObjCObjectPointerType())
@@ -6826,8 +7012,7 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
/*warn=*/false);
} else {
// Check protocols.
- Method = S.LookupMethodInQualifiedType(IsEqualSel,
- cast<ObjCObjectPointerType>(Type),
+ Method = S.LookupMethodInQualifiedType(IsEqualSel, Type,
/*instance=*/true);
}
}
@@ -6846,6 +7031,48 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
return true;
}
+Sema::ObjCLiteralKind Sema::CheckLiteralKind(Expr *FromE) {
+ FromE = FromE->IgnoreParenImpCasts();
+ switch (FromE->getStmtClass()) {
+ default:
+ break;
+ case Stmt::ObjCStringLiteralClass:
+ // "string literal"
+ return LK_String;
+ case Stmt::ObjCArrayLiteralClass:
+ // "array literal"
+ return LK_Array;
+ case Stmt::ObjCDictionaryLiteralClass:
+ // "dictionary literal"
+ return LK_Dictionary;
+ case Stmt::BlockExprClass:
+ return LK_Block;
+ case Stmt::ObjCBoxedExprClass: {
+ Expr *Inner = cast<ObjCBoxedExpr>(FromE)->getSubExpr()->IgnoreParens();
+ switch (Inner->getStmtClass()) {
+ case Stmt::IntegerLiteralClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::ObjCBoolLiteralExprClass:
+ case Stmt::CXXBoolLiteralExprClass:
+ // "numeric literal"
+ return LK_Numeric;
+ case Stmt::ImplicitCastExprClass: {
+ CastKind CK = cast<CastExpr>(Inner)->getCastKind();
+ // Boolean literals can be represented by implicit casts.
+ if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast)
+ return LK_Numeric;
+ break;
+ }
+ default:
+ break;
+ }
+ return LK_Boxed;
+ }
+ }
+ return LK_None;
+}
+
static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS,
BinaryOperator::Opcode Opc){
@@ -6866,61 +7093,15 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
return;
// This should be kept in sync with warn_objc_literal_comparison.
- // LK_String should always be last, since it has its own warning flag.
- enum {
- LK_Array,
- LK_Dictionary,
- LK_Numeric,
- LK_Boxed,
- LK_String
- } LiteralKind;
-
- Literal = Literal->IgnoreParenImpCasts();
- switch (Literal->getStmtClass()) {
- case Stmt::ObjCStringLiteralClass:
- // "string literal"
- LiteralKind = LK_String;
- break;
- case Stmt::ObjCArrayLiteralClass:
- // "array literal"
- LiteralKind = LK_Array;
- break;
- case Stmt::ObjCDictionaryLiteralClass:
- // "dictionary literal"
- LiteralKind = LK_Dictionary;
- break;
- case Stmt::ObjCBoxedExprClass: {
- Expr *Inner = cast<ObjCBoxedExpr>(Literal)->getSubExpr();
- switch (Inner->getStmtClass()) {
- case Stmt::IntegerLiteralClass:
- case Stmt::FloatingLiteralClass:
- case Stmt::CharacterLiteralClass:
- case Stmt::ObjCBoolLiteralExprClass:
- case Stmt::CXXBoolLiteralExprClass:
- // "numeric literal"
- LiteralKind = LK_Numeric;
- break;
- case Stmt::ImplicitCastExprClass: {
- CastKind CK = cast<CastExpr>(Inner)->getCastKind();
- // Boolean literals can be represented by implicit casts.
- if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast) {
- LiteralKind = LK_Numeric;
- break;
- }
- // FALLTHROUGH
- }
- default:
- // "boxed expression"
- LiteralKind = LK_Boxed;
- break;
- }
- break;
- }
- default:
+ // LK_String should always be after the other literals, since it has its own
+ // warning flag.
+ Sema::ObjCLiteralKind LiteralKind = S.CheckLiteralKind(Literal);
+ assert(LiteralKind != Sema::LK_Block);
+ if (LiteralKind == Sema::LK_None) {
llvm_unreachable("Unknown Objective-C object literal kind");
}
- if (LiteralKind == LK_String)
+ if (LiteralKind == Sema::LK_String)
S.Diag(Loc, diag::warn_objc_string_literal_comparison)
<< Literal->getSourceRange();
else
@@ -6931,11 +7112,12 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
hasIsEqualMethod(S, LHS.get(), RHS.get())) {
SourceLocation Start = LHS.get()->getLocStart();
SourceLocation End = S.PP.getLocForEndOfToken(RHS.get()->getLocEnd());
- SourceRange OpRange(Loc, S.PP.getLocForEndOfToken(Loc));
+ CharSourceRange OpRange =
+ CharSourceRange::getCharRange(Loc, S.PP.getLocForEndOfToken(Loc));
S.Diag(Loc, diag::note_objc_literal_comparison_isequal)
<< FixItHint::CreateInsertion(Start, Opc == BO_EQ ? "[" : "![")
- << FixItHint::CreateReplacement(OpRange, "isEqual:")
+ << FixItHint::CreateReplacement(OpRange, " isEqual:")
<< FixItHint::CreateInsertion(End, "]");
}
}
@@ -6959,7 +7141,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts();
Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts();
- checkEnumComparison(*this, Loc, LHS, RHS);
+ checkEnumComparison(*this, Loc, LHS.get(), RHS.get());
if (!LHSType->hasFloatingRepresentation() &&
!(LHSType->isBlockPointerType() && IsRelational) &&
@@ -7109,7 +7291,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
&& !LHSIsNull && !RHSIsNull) {
diagnoseFunctionPointerToVoidComparison(
- *this, Loc, LHS, RHS, /*isError*/ isSFINAEContext());
+ *this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext());
if (isSFINAEContext())
return QualType();
@@ -7396,7 +7578,10 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
// Ensure that either both operands are of the same vector type, or
// one operand is of a vector type and the other is of its element type.
QualType vType = CheckVectorOperands(LHS, RHS, Loc, false);
- if (vType.isNull() || vType->isFloatingType())
+ if (vType.isNull())
+ return InvalidOperands(Loc, LHS, RHS);
+ if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 &&
+ vType->hasFloatingRepresentation())
return InvalidOperands(Loc, LHS, RHS);
return GetSignedVectorType(LHS.get()->getType());
@@ -7472,8 +7657,17 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
RHS.get()->getLocEnd()));
}
}
-
+
if (!Context.getLangOpts().CPlusPlus) {
+ // OpenCL v1.1 s6.3.g: The logical operators and (&&), or (||) do
+ // not operate on the built-in scalar and vector float types.
+ if (Context.getLangOpts().OpenCL &&
+ Context.getLangOpts().OpenCLVersion < 120) {
+ if (LHS.get()->getType()->isFloatingType() ||
+ RHS.get()->getType()->isFloatingType())
+ return InvalidOperands(Loc, LHS, RHS);
+ }
+
LHS = UsualUnaryConversions(LHS.take());
if (LHS.isInvalid())
return QualType();
@@ -7999,7 +8193,9 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
if (PTy->getKind() == BuiltinType::Overload) {
if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) {
- S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
+ assert(cast<UnaryOperator>(OrigOp.get()->IgnoreParens())->getOpcode()
+ == UO_AddrOf);
+ S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
@@ -8043,10 +8239,10 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
unsigned AddressOfError = AO_No_Error;
- if (lval == Expr::LV_ClassTemporary) {
- bool sfinae = S.isSFINAEContext();
- S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary
- : diag::ext_typecheck_addrof_class_temporary)
+ if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
+ bool sfinae = (bool)S.isSFINAEContext();
+ S.Diag(OpLoc, S.isSFINAEContext() ? diag::err_typecheck_addrof_temporary
+ : diag::ext_typecheck_addrof_temporary)
<< op->getType() << op->getSourceRange();
if (sfinae)
return QualType();
@@ -8094,9 +8290,8 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
if (isa<PseudoObjectExpr>(op)) {
AddressOfError = AO_Property_Expansion;
} else {
- // FIXME: emit more specific diag...
S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
- << op->getSourceRange();
+ << op->getType() << op->getSourceRange();
return QualType();
}
}
@@ -8312,7 +8507,7 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHSExpr, Expr *RHSExpr) {
- if (getLangOpts().CPlusPlus0x && isa<InitListExpr>(RHSExpr)) {
+ if (getLangOpts().CPlusPlus11 && isa<InitListExpr>(RHSExpr)) {
// The syntax only allows initializer lists on the RHS of assignment,
// so we don't need to worry about accepting invalid code for
// non-assignment operators.
@@ -8445,6 +8640,24 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
CheckArrayAccess(LHS.get());
CheckArrayAccess(RHS.get());
+ if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(LHS.get()->IgnoreParenCasts())) {
+ NamedDecl *ObjectSetClass = LookupSingleName(TUScope,
+ &Context.Idents.get("object_setClass"),
+ SourceLocation(), LookupOrdinaryName);
+ if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) {
+ SourceLocation RHSLocEnd = PP.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), ",") <<
+ FixItHint::CreateInsertion(RHSLocEnd, ")");
+ }
+ else
+ Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign);
+ }
+ else if (const ObjCIvarRefExpr *OIRE =
+ dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts()))
+ DiagnoseDirectIsaAccess(*this, OIRE, OpLoc, RHS.get());
+
if (CompResultTy.isNull())
return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc,
ResultTy, VK, OK, OpLoc,
@@ -8467,46 +8680,38 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
SourceLocation OpLoc, Expr *LHSExpr,
Expr *RHSExpr) {
- typedef BinaryOperator BinOp;
- BinOp::Opcode LHSopc = static_cast<BinOp::Opcode>(-1),
- RHSopc = static_cast<BinOp::Opcode>(-1);
- if (BinOp *BO = dyn_cast<BinOp>(LHSExpr))
- LHSopc = BO->getOpcode();
- if (BinOp *BO = dyn_cast<BinOp>(RHSExpr))
- RHSopc = BO->getOpcode();
-
- // Subs are not binary operators.
- if (LHSopc == -1 && RHSopc == -1)
+ BinaryOperator *LHSBO = dyn_cast<BinaryOperator>(LHSExpr);
+ BinaryOperator *RHSBO = dyn_cast<BinaryOperator>(RHSExpr);
+
+ // Check that one of the sides is a comparison operator.
+ bool isLeftComp = LHSBO && LHSBO->isComparisonOp();
+ bool isRightComp = RHSBO && RHSBO->isComparisonOp();
+ if (!isLeftComp && !isRightComp)
return;
// Bitwise operations are sometimes used as eager logical ops.
// Don't diagnose this.
- if ((BinOp::isComparisonOp(LHSopc) || BinOp::isBitwiseOp(LHSopc)) &&
- (BinOp::isComparisonOp(RHSopc) || BinOp::isBitwiseOp(RHSopc)))
+ bool isLeftBitwise = LHSBO && LHSBO->isBitwiseOp();
+ bool isRightBitwise = RHSBO && RHSBO->isBitwiseOp();
+ if ((isLeftComp || isLeftBitwise) && (isRightComp || isRightBitwise))
return;
- bool isLeftComp = BinOp::isComparisonOp(LHSopc);
- bool isRightComp = BinOp::isComparisonOp(RHSopc);
- if (!isLeftComp && !isRightComp) return;
-
SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(),
OpLoc)
: SourceRange(OpLoc, RHSExpr->getLocEnd());
- StringRef OpStr = isLeftComp ? BinOp::getOpcodeStr(LHSopc)
- : BinOp::getOpcodeStr(RHSopc);
+ StringRef OpStr = isLeftComp ? LHSBO->getOpcodeStr() : RHSBO->getOpcodeStr();
SourceRange ParensRange = isLeftComp ?
- SourceRange(cast<BinOp>(LHSExpr)->getRHS()->getLocStart(),
- RHSExpr->getLocEnd())
- : SourceRange(LHSExpr->getLocStart(),
- cast<BinOp>(RHSExpr)->getLHS()->getLocStart());
+ SourceRange(LHSBO->getRHS()->getLocStart(), RHSExpr->getLocEnd())
+ : SourceRange(LHSExpr->getLocStart(), RHSBO->getLHS()->getLocStart());
Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel)
- << DiagRange << BinOp::getOpcodeStr(Opc) << OpStr;
+ << DiagRange << BinaryOperator::getOpcodeStr(Opc) << OpStr;
SuggestParentheses(Self, OpLoc,
Self.PDiag(diag::note_precedence_silence) << OpStr,
(isLeftComp ? LHSExpr : RHSExpr)->getSourceRange());
SuggestParentheses(Self, OpLoc,
- Self.PDiag(diag::note_precedence_bitwise_first) << BinOp::getOpcodeStr(Opc),
+ Self.PDiag(diag::note_precedence_bitwise_first)
+ << BinaryOperator::getOpcodeStr(Opc),
ParensRange);
}
@@ -8806,7 +9011,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
case UO_Not: // bitwise complement
Input = UsualUnaryConversions(Input.take());
- if (Input.isInvalid()) return ExprError();
+ if (Input.isInvalid())
+ return ExprError();
resultType = Input.get()->getType();
if (resultType->isDependentType())
break;
@@ -8814,12 +9020,22 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
if (resultType->isComplexType() || resultType->isComplexIntegerType())
// C99 does not support '~' for complex conjugation.
Diag(OpLoc, diag::ext_integer_complement_complex)
- << resultType << Input.get()->getSourceRange();
+ << resultType << Input.get()->getSourceRange();
else if (resultType->hasIntegerRepresentation())
break;
- else {
+ else if (resultType->isExtVectorType()) {
+ if (Context.getLangOpts().OpenCL) {
+ // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate
+ // on vector float types.
+ QualType T = resultType->getAs<ExtVectorType>()->getElementType();
+ if (!T->isIntegerType())
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << resultType << Input.get()->getSourceRange());
+ }
+ break;
+ } else {
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
- << resultType << Input.get()->getSourceRange());
+ << resultType << Input.get()->getSourceRange());
}
break;
@@ -8830,7 +9046,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
resultType = Input.get()->getType();
// Though we still have to promote half FP to float...
- if (resultType->isHalfType()) {
+ if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) {
Input = ImpCastExprToType(Input.take(), Context.FloatTy, CK_FloatingCast).take();
resultType = Context.FloatTy;
}
@@ -8844,8 +9060,24 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
// operand contextually converted to bool.
Input = ImpCastExprToType(Input.take(), Context.BoolTy,
ScalarTypeToBooleanCastKind(resultType));
+ } else if (Context.getLangOpts().OpenCL &&
+ Context.getLangOpts().OpenCLVersion < 120) {
+ // OpenCL v1.1 6.3.h: The logical operator not (!) does not
+ // operate on scalar float types.
+ if (!resultType->isIntegerType())
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << resultType << Input.get()->getSourceRange());
}
} else if (resultType->isExtVectorType()) {
+ if (Context.getLangOpts().OpenCL &&
+ Context.getLangOpts().OpenCLVersion < 120) {
+ // OpenCL v1.1 6.3.h: The logical operator not (!) does not
+ // operate on vector float types.
+ QualType T = resultType->getAs<ExtVectorType>()->getElementType();
+ if (!T->isIntegerType())
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << resultType << Input.get()->getSourceRange());
+ }
// Vector logical not returns the signed variant of the operand type.
resultType = GetSignedVectorType(resultType);
break;
@@ -9210,9 +9442,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// If type is not a standard-layout class (Clause 9), the results are
// undefined.
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- bool IsSafe = LangOpts.CPlusPlus0x? CRD->isStandardLayout() : CRD->isPOD();
+ bool IsSafe = LangOpts.CPlusPlus11? CRD->isStandardLayout() : CRD->isPOD();
unsigned DiagID =
- LangOpts.CPlusPlus0x? diag::warn_offsetof_non_standardlayout_type
+ LangOpts.CPlusPlus11? diag::warn_offsetof_non_standardlayout_type
: diag::warn_offsetof_non_pod_type;
if (!IsSafe && !DidWarnAboutNonPOD &&
@@ -9379,8 +9611,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
FunctionProtoType::ExtProtoInfo EPI;
EPI.HasTrailingReturn = false;
EPI.TypeQuals |= DeclSpec::TQ_const;
- T = Context.getFunctionType(Context.DependentTy, /*Args=*/0, /*NumArgs=*/0,
- EPI);
+ T = Context.getFunctionType(Context.DependentTy, ArrayRef<QualType>(), EPI);
Sig = Context.getTrivialTypeSourceInfo(T);
}
@@ -9394,8 +9625,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
FunctionProtoTypeLoc ExplicitSignature;
TypeLoc tmp = Sig->getTypeLoc().IgnoreParens();
- if (isa<FunctionProtoTypeLoc>(tmp)) {
- ExplicitSignature = cast<FunctionProtoTypeLoc>(tmp);
+ if ((ExplicitSignature = tmp.getAs<FunctionProtoTypeLoc>())) {
// Check whether that explicit signature was synthesized by
// GetTypeForDeclarator. If so, don't save that as part of the
@@ -9560,7 +9790,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
if (isa<FunctionNoProtoType>(FTy)) {
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = Ext;
- BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI);
+ BlockTy = Context.getFunctionType(RetTy, ArrayRef<QualType>(), EPI);
// Otherwise, if we don't need to change anything about the function type,
// preserve its sugar structure.
@@ -9574,17 +9804,18 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals = 0; // FIXME: silently?
EPI.ExtInfo = Ext;
- BlockTy = Context.getFunctionType(RetTy,
- FPT->arg_type_begin(),
- FPT->getNumArgs(),
- EPI);
+ BlockTy =
+ Context.getFunctionType(RetTy,
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI);
}
// If we don't have a function type, just build one from nothing.
} else {
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn);
- BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI);
+ BlockTy = Context.getFunctionType(RetTy, ArrayRef<QualType>(), EPI);
}
DiagnoseUnusedParameters(BSI->TheDecl->param_begin(),
@@ -9715,11 +9946,11 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float))
PromoteType = Context.DoubleTy;
if (!PromoteType.isNull())
- Diag(TInfo->getTypeLoc().getBeginLoc(),
- diag::warn_second_parameter_to_va_arg_never_compatible)
- << TInfo->getType()
- << PromoteType
- << TInfo->getTypeLoc().getSourceRange();
+ DiagRuntimeBehavior(TInfo->getTypeLoc().getBeginLoc(), E,
+ PDiag(diag::warn_second_parameter_to_va_arg_never_compatible)
+ << TInfo->getType()
+ << PromoteType
+ << TInfo->getTypeLoc().getSourceRange());
}
QualType T = TInfo->getType().getNonLValueExprType(Context);
@@ -9932,6 +10163,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
if (CheckInferredResultType)
EmitRelatedResultTypeNote(SrcExpr);
+
+ if (Action == AA_Returning && ConvTy == IncompatiblePointer)
+ EmitRelatedResultTypeNoteForReturn(DstType);
if (Complained)
*Complained = true;
@@ -9980,7 +10214,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
bool AllowFold) {
SourceLocation DiagLoc = E->getLocStart();
- if (getLangOpts().CPlusPlus0x) {
+ if (getLangOpts().CPlusPlus11) {
// C++11 [expr.const]p5:
// If an expression of literal class type is used in a context where an
// integral constant expression is required, then that class type shall
@@ -10107,14 +10341,14 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
// Circumvent ICE checking in C++11 to avoid evaluating the expression twice
// in the non-ICE case.
- if (!getLangOpts().CPlusPlus0x && E->isIntegerConstantExpr(Context)) {
+ if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
if (Result)
*Result = E->EvaluateKnownConstInt(Context);
return Owned(E);
}
Expr::EvalResult EvalResult;
- llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ SmallVector<PartialDiagnosticAt, 8> Notes;
EvalResult.Diag = &Notes;
// Try to evaluate the expression, and produce diagnostics explaining why it's
@@ -10125,7 +10359,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
// In C++11, we can rely on diagnostics being produced for any expression
// which is not a constant expression. If no diagnostics were produced, then
// this is a constant expression.
- if (Folded && getLangOpts().CPlusPlus0x && Notes.empty()) {
+ if (Folded && getLangOpts().CPlusPlus11 && Notes.empty()) {
if (Result)
*Result = EvalResult.Val.getInt();
return Owned(E);
@@ -10211,7 +10445,7 @@ namespace {
};
}
-ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) {
+ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) {
assert(ExprEvalContexts.back().Context == Unevaluated &&
"Should only transform unevaluated expressions");
ExprEvalContexts.back().Context =
@@ -10302,7 +10536,7 @@ void Sema::DiscardCleanupsInEvaluationContext() {
ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) {
if (!E->getType()->isVariablyModifiedType())
return E;
- return TranformToPotentiallyEvaluated(E);
+ return TransformToPotentiallyEvaluated(E);
}
static bool IsPotentiallyEvaluatedContext(Sema &SemaRef) {
@@ -10395,6 +10629,9 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
if (!Constructor->isUsed(false))
DefineImplicitMoveConstructor(Loc, Constructor);
}
+ } else if (Constructor->getInheritedConstructor()) {
+ if (!Constructor->isUsed(false))
+ DefineInheritingConstructor(Loc, Constructor);
}
MarkVTableUsed(Loc, Constructor->getParent());
@@ -10488,13 +10725,26 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
}
// Keep track of used but undefined functions.
- if (!Func->isPure() && !Func->hasBody() &&
- Func->getLinkage() != ExternalLinkage) {
- SourceLocation &old = UndefinedInternals[Func->getCanonicalDecl()];
- if (old.isInvalid()) old = Loc;
+ if (!Func->isDefined()) {
+ if (mightHaveNonExternalLinkage(Func))
+ UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
+ else if (Func->getMostRecentDecl()->isInlined() &&
+ (LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
+ !Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>())
+ UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
+ }
+
+ // Normally the must current decl is marked used while processing the use and
+ // any subsequent decls are marked used by decl merging. This fails with
+ // template instantiation since marking can happen at the end of the file
+ // and, because of the two phase lookup, this function is called with at
+ // decl in the middle of a decl chain. We loop to maintain the invariant
+ // that once a decl is used, all decls after it are also used.
+ for (FunctionDecl *F = Func->getMostRecentDecl();; F = F->getPreviousDecl()) {
+ F->setUsed(true);
+ if (F == Func)
+ break;
}
-
- Func->setUsed(true);
}
static void
@@ -10572,7 +10822,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
// Introduce a new evaluation context for the initialization, so
// that temporaries introduced as part of the capture are retained
// to be re-"exported" from the lambda expression itself.
- S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+ EnterExpressionEvaluationContext scope(S, Sema::PotentiallyEvaluated);
// C++ [expr.prim.labda]p12:
// An entity captured by a lambda-expression is odr-used (3.2) in
@@ -10604,7 +10854,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
= VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
IterationVarName, SizeType,
S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None, SC_None);
+ SC_None);
IndexVariables.push_back(IterationVar);
LSI->ArrayIndexVars.push_back(IterationVar);
@@ -10623,7 +10873,6 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
if (Subscript.isInvalid()) {
S.CleanupVarDeclMarking();
S.DiscardCleanupsInEvaluationContext();
- S.PopExpressionEvaluationContext();
return ExprError();
}
@@ -10659,7 +10908,6 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
// Exit the expression evaluation context used for the capture.
S.CleanupVarDeclMarking();
S.DiscardCleanupsInEvaluationContext();
- S.PopExpressionEvaluationContext();
return Result;
}
@@ -10748,7 +10996,22 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
}
return true;
}
-
+ // Prohibit structs with flexible array members too.
+ // We cannot capture what is in the tail end of the struct.
+ if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) {
+ if (VTTy->getDecl()->hasFlexibleArrayMember()) {
+ if (BuildAndDiagnose) {
+ if (IsBlock)
+ Diag(Loc, diag::err_ref_flexarray_type);
+ else
+ Diag(Loc, diag::err_lambda_capture_flexarray_type)
+ << Var->getDeclName();
+ Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return true;
+ }
+ }
// Lambdas are not allowed to capture __block variables; they don't
// support the expected semantics.
if (IsLambda && HasBlocksAttr) {
@@ -10830,13 +11093,18 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
// actually requires the destructor.
if (isa<ParmVarDecl>(Var))
FinalizeVarWithDestructor(Var, Record);
-
+
+ // Enter a new evaluation context to insulate the copy
+ // full-expression.
+ EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
+
// According to the blocks spec, the capture of a variable from
// the stack requires a const copy constructor. This is not true
// of the copy/move done to move a __block variable to the heap.
- Expr *DeclRef = new (Context) DeclRefExpr(Var, false,
+ Expr *DeclRef = new (Context) DeclRefExpr(Var, Nested,
DeclRefType.withConst(),
VK_LValue, Loc);
+
ExprResult Result
= PerformCopyInitialization(
InitializedEntity::InitializeBlock(Var->getLocation(),
@@ -10921,7 +11189,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
if (BuildAndDiagnose) {
ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType,
DeclRefType, Loc,
- I == N-1);
+ Nested);
if (!Result.isInvalid())
CopyExpr = Result.take();
}
@@ -10978,7 +11246,7 @@ static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var,
if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
Var->getLinkage() != ExternalLinkage &&
!(Var->isStaticDataMember() && Var->hasInit())) {
- SourceLocation &old = SemaRef.UndefinedInternals[Var->getCanonicalDecl()];
+ SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
if (old.isInvalid()) old = Loc;
}
@@ -11090,13 +11358,13 @@ void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
}
static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
- Decl *D, Expr *E) {
+ Decl *D, Expr *E, bool OdrUse) {
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
DoMarkVarDeclReferenced(SemaRef, Loc, Var, E);
return;
}
- SemaRef.MarkAnyDeclReferenced(Loc, D);
+ SemaRef.MarkAnyDeclReferenced(Loc, D, OdrUse);
// If this is a call to a method via a cast, also mark the method in the
// derived class used in case codegen can devirtualize the call.
@@ -11111,32 +11379,58 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
if (!MostDerivedClassDecl)
return;
CXXMethodDecl *DM = MD->getCorrespondingMethodInClass(MostDerivedClassDecl);
- if (!DM)
+ if (!DM || DM->isPure())
return;
- SemaRef.MarkAnyDeclReferenced(Loc, DM);
+ SemaRef.MarkAnyDeclReferenced(Loc, DM, OdrUse);
}
/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr.
void Sema::MarkDeclRefReferenced(DeclRefExpr *E) {
- MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E);
+ // TODO: update this with DR# once a defect report is filed.
+ // C++11 defect. The address of a pure member should not be an ODR use, even
+ // if it's a qualified reference.
+ bool OdrUse = true;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getDecl()))
+ if (Method->isVirtual())
+ OdrUse = false;
+ MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse);
}
/// \brief Perform reference-marking and odr-use handling for a MemberExpr.
void Sema::MarkMemberReferenced(MemberExpr *E) {
- MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E);
+ // C++11 [basic.def.odr]p2:
+ // A non-overloaded function whose name appears as a potentially-evaluated
+ // expression or a member of a set of candidate functions, if selected by
+ // overload resolution when referred to from a potentially-evaluated
+ // 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 (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl()))
+ if (Method->isPure())
+ OdrUse = false;
+ }
+ SourceLocation Loc = E->getMemberLoc().isValid() ?
+ E->getMemberLoc() : E->getLocStart();
+ MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, OdrUse);
}
/// \brief Perform marking for a reference to an arbitrary declaration. It
/// marks the declaration referenced, and performs odr-use checking for functions
/// and variables. This method should not be used when building an normal
/// expression which refers to a variable.
-void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D) {
- if (VarDecl *VD = dyn_cast<VarDecl>(D))
- MarkVariableReferenced(Loc, VD);
- else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- MarkFunctionReferenced(Loc, FD);
- else
- D->setReferenced();
+void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse) {
+ if (OdrUse) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ MarkVariableReferenced(Loc, VD);
+ return;
+ }
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ MarkFunctionReferenced(Loc, FD);
+ return;
+ }
+ }
+ D->setReferenced();
}
namespace {
@@ -11161,7 +11455,7 @@ bool MarkReferencedDecls::TraverseTemplateArgument(
const TemplateArgument &Arg) {
if (Arg.getKind() == TemplateArgument::Declaration) {
if (Decl *D = Arg.getAsDecl())
- S.MarkAnyDeclReferenced(Loc, D);
+ S.MarkAnyDeclReferenced(Loc, D, true);
}
return Inherited::TraverseTemplateArgument(Arg);
@@ -11685,10 +11979,11 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
// Rebuild the function type, replacing the result type with DestType.
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType))
- DestType = S.Context.getFunctionType(DestType,
- Proto->arg_type_begin(),
- Proto->getNumArgs(),
- Proto->getExtProtoInfo());
+ DestType =
+ S.Context.getFunctionType(DestType,
+ ArrayRef<QualType>(Proto->arg_type_begin(),
+ Proto->getNumArgs()),
+ Proto->getExtProtoInfo());
else
DestType = S.Context.getFunctionNoProtoType(DestType,
FnType->getExtInfo());
@@ -11850,6 +12145,29 @@ ExprResult Sema::forceUnknownAnyToType(Expr *E, QualType ToType) {
return RebuildUnknownAnyExpr(*this, ToType).Visit(E);
}
+ExprResult Sema::checkUnknownAnyArg(SourceLocation callLoc,
+ Expr *arg, QualType &paramType) {
+ // If the syntactic form of the argument is not an explicit cast of
+ // any sort, just do default argument promotion.
+ ExplicitCastExpr *castArg = dyn_cast<ExplicitCastExpr>(arg->IgnoreParens());
+ if (!castArg) {
+ ExprResult result = DefaultArgumentPromotion(arg);
+ if (result.isInvalid()) return ExprError();
+ paramType = result.get()->getType();
+ return result;
+ }
+
+ // Otherwise, use the type that was written in the explicit cast.
+ assert(!arg->hasPlaceholderType());
+ paramType = castArg->getTypeAsWritten();
+
+ // Copy-initialize a parameter of that type.
+ InitializedEntity entity =
+ InitializedEntity::InitializeParameter(Context, paramType,
+ /*consumed*/ false);
+ return PerformCopyInitialization(entity, callLoc, Owned(arg));
+}
+
static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
Expr *orig = E;
unsigned diagID = diag::err_uncasted_use_of_unknown_any;
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 0919bc5b6fa4..3f2cb026730d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -13,30 +13,68 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/TemplateDeduction.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/CharUnits.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
-#include "TypeLocBuilder.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
using namespace sema;
+/// \brief Handle the result of the special case name lookup for inheriting
+/// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as
+/// constructor names in member using declarations, even if 'X' is not the
+/// name of the corresponding type.
+ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ IdentifierInfo &Name) {
+ NestedNameSpecifier *NNS = SS.getScopeRep();
+
+ // Convert the nested-name-specifier into a type.
+ QualType Type;
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ Type = QualType(NNS->getAsType(), 0);
+ break;
+
+ case NestedNameSpecifier::Identifier:
+ // Strip off the last layer of the nested-name-specifier and build a
+ // typename type for it.
+ assert(NNS->getAsIdentifier() == &Name && "not a constructor name");
+ Type = Context.getDependentNameType(ETK_None, NNS->getPrefix(),
+ NNS->getAsIdentifier());
+ break;
+
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ llvm_unreachable("Nested name specifier is not a type for inheriting ctor");
+ }
+
+ // This reference to the type is located entirely at the location of the
+ // final identifier in the qualified-id.
+ return CreateParsedType(Type,
+ Context.getTrivialTypeSourceInfo(Type, NameLoc));
+}
+
ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
IdentifierInfo &II,
SourceLocation NameLoc,
@@ -263,8 +301,16 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
} else if (ObjectTypePtr)
Diag(NameLoc, diag::err_ident_in_dtor_not_a_type)
<< &II;
- else
- Diag(NameLoc, diag::err_destructor_class_name);
+ else {
+ SemaDiagnosticBuilder DtorDiag = Diag(NameLoc,
+ diag::err_destructor_class_name);
+ if (S) {
+ const DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+ if (const CXXRecordDecl *Class = dyn_cast_or_null<CXXRecordDecl>(Ctx))
+ DtorDiag << FixItHint::CreateReplacement(SourceRange(NameLoc),
+ Class->getNameAsString());
+ }
+ }
return ParsedType();
}
@@ -336,7 +382,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
if (RecordD->isPolymorphic() && E->isGLValue()) {
// The subexpression is potentially evaluated; switch the context
// and recheck the subexpression.
- ExprResult Result = TranformToPotentiallyEvaluated(E);
+ ExprResult Result = TransformToPotentiallyEvaluated(E);
if (Result.isInvalid()) return ExprError();
E = Result.take();
@@ -1041,13 +1087,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
} else if (Initializer && isa<InitListExpr>(Initializer))
initStyle = CXXNewExpr::ListInit;
else {
- // In template instantiation, the initializer could be a CXXDefaultArgExpr
- // unwrapped from a CXXConstructExpr that was implicitly built. There is no
- // particularly sane way we can handle this (especially since it can even
- // occur for array new), so we throw the initializer away and have it be
- // rebuilt.
- if (Initializer && isa<CXXDefaultArgExpr>(Initializer))
- Initializer = 0;
assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) ||
isa<CXXConstructExpr>(Initializer)) &&
"Initializer expression that cannot have been implicitly created.");
@@ -1056,20 +1095,20 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
Expr **Inits = &Initializer;
unsigned NumInits = Initializer ? 1 : 0;
- if (initStyle == CXXNewExpr::CallInit) {
- if (ParenListExpr *List = dyn_cast<ParenListExpr>(Initializer)) {
- Inits = List->getExprs();
- NumInits = List->getNumExprs();
- } else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Initializer)){
- if (!isa<CXXTemporaryObjectExpr>(CCE)) {
- // Can happen in template instantiation. Since this is just an implicit
- // construction, we just take it apart and rebuild it.
- Inits = CCE->getArgs();
- NumInits = CCE->getNumArgs();
- }
- }
+ if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) {
+ assert(initStyle == CXXNewExpr::CallInit && "paren init for non-call init");
+ Inits = List->getExprs();
+ NumInits = List->getNumExprs();
}
+ // Determine whether we've already built the initializer.
+ bool HaveCompleteInit = false;
+ if (Initializer && isa<CXXConstructExpr>(Initializer) &&
+ !isa<CXXTemporaryObjectExpr>(Initializer))
+ HaveCompleteInit = true;
+ else if (Initializer && isa<ImplicitValueInitExpr>(Initializer))
+ HaveCompleteInit = true;
+
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
AutoType *AT = 0;
if (TypeMayContainAuto &&
@@ -1147,7 +1186,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
QualType T) {
return S.Diag(Loc, diag::err_array_size_not_integral)
- << S.getLangOpts().CPlusPlus0x << T;
+ << S.getLangOpts().CPlusPlus11 << T;
}
virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
@@ -1185,7 +1224,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
QualType T,
QualType ConvTy) {
return S.Diag(Loc,
- S.getLangOpts().CPlusPlus0x
+ S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_array_size_conversion
: diag::ext_array_size_conversion)
<< T << ConvTy->isEnumeralType() << ConvTy;
@@ -1221,7 +1260,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (Value < llvm::APSInt(
llvm::APInt::getNullValue(Value.getBitWidth()),
Value.isUnsigned())) {
- if (getLangOpts().CPlusPlus0x)
+ if (getLangOpts().CPlusPlus11)
Diag(ArraySize->getLocStart(),
diag::warn_typecheck_negative_array_new_size)
<< ArraySize->getSourceRange();
@@ -1233,7 +1272,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
unsigned ActiveSizeBits =
ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
- if (getLangOpts().CPlusPlus0x)
+ if (getLangOpts().CPlusPlus11)
Diag(ArraySize->getLocStart(),
diag::warn_array_new_too_large)
<< Value.toString(10)
@@ -1341,9 +1380,12 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
}
}
+ // If we can perform the initialization, and we've not already done so,
+ // do it now.
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(
- llvm::makeArrayRef(Inits, NumInits))) {
+ llvm::makeArrayRef(Inits, NumInits)) &&
+ !HaveCompleteInit) {
// C++11 [expr.new]p15:
// A new-expression that creates an object of type T initializes that
// object as follows:
@@ -1379,10 +1421,14 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
}
// Mark the new and delete operators as referenced.
- if (OperatorNew)
+ if (OperatorNew) {
+ DiagnoseUseOfDecl(OperatorNew, StartLoc);
MarkFunctionReferenced(StartLoc, OperatorNew);
- if (OperatorDelete)
+ }
+ if (OperatorDelete) {
+ DiagnoseUseOfDecl(OperatorDelete, StartLoc);
MarkFunctionReferenced(StartLoc, OperatorDelete);
+ }
// C++0x [expr.new]p17:
// If the new expression creates an array of objects of class type,
@@ -1594,8 +1640,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
EPI.Variadic = Proto->isVariadic();
ExpectedFunctionType
- = Context.getFunctionType(Context.VoidTy, ArgTypes.data(),
- ArgTypes.size(), EPI);
+ = Context.getFunctionType(Context.VoidTy, ArgTypes, EPI);
}
for (LookupResult::iterator D = FoundDelete.begin(),
@@ -1641,7 +1686,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// as a placement deallocation function, would have been
// selected as a match for the allocation function, the program
// is ill-formed.
- if (NumPlaceArgs && getLangOpts().CPlusPlus0x &&
+ if (NumPlaceArgs && getLangOpts().CPlusPlus11 &&
isNonPlacementDeallocationFunction(OperatorDelete)) {
Diag(StartLoc, diag::err_placement_new_non_placement_delete)
<< SourceRange(PlaceArgs[0]->getLocStart(),
@@ -1817,7 +1862,7 @@ void Sema::DeclareGlobalNewDelete() {
// lookup.
// Note that the C++0x versions of operator delete are deallocation functions,
// and thus are implicitly noexcept.
- if (!StdBadAlloc && !getLangOpts().CPlusPlus0x) {
+ if (!StdBadAlloc && !getLangOpts().CPlusPlus11) {
// The "std::bad_alloc" class has not yet been declared, so build it
// implicitly.
StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class,
@@ -1857,8 +1902,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
// Check if this function is already declared.
{
- DeclContext::lookup_iterator Alloc, AllocEnd;
- for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
+ DeclContext::lookup_result R = GlobalCtx->lookup(Name);
+ for (DeclContext::lookup_iterator Alloc = R.begin(), AllocEnd = R.end();
Alloc != AllocEnd; ++Alloc) {
// Only look at non-template functions, as it is the predefined,
// non-templated allocation function we are trying to declare here.
@@ -1880,29 +1925,28 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
bool HasBadAllocExceptionSpec
= (Name.getCXXOverloadedOperator() == OO_New ||
Name.getCXXOverloadedOperator() == OO_Array_New);
- if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus0x) {
+ if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus11) {
assert(StdBadAlloc && "Must have std::bad_alloc declared");
BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
}
FunctionProtoType::ExtProtoInfo EPI;
if (HasBadAllocExceptionSpec) {
- if (!getLangOpts().CPlusPlus0x) {
+ if (!getLangOpts().CPlusPlus11) {
EPI.ExceptionSpecType = EST_Dynamic;
EPI.NumExceptions = 1;
EPI.Exceptions = &BadAllocType;
}
} else {
- EPI.ExceptionSpecType = getLangOpts().CPlusPlus0x ?
+ EPI.ExceptionSpecType = getLangOpts().CPlusPlus11 ?
EST_BasicNoexcept : EST_DynamicNone;
}
- QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI);
+ QualType FnType = Context.getFunctionType(Return, Argument, EPI);
FunctionDecl *Alloc =
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
SourceLocation(), Name,
- FnType, /*TInfo=*/0, SC_None,
- SC_None, false, true);
+ FnType, /*TInfo=*/0, SC_None, false, true);
Alloc->setImplicit();
if (AddMallocAttr)
@@ -1911,7 +1955,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
SourceLocation(), 0,
Argument, /*TInfo=*/0,
- SC_None, SC_None, 0);
+ SC_None, 0);
Alloc->setParams(Param);
// FIXME: Also add this declaration to the IdentifierResolver, but
@@ -2030,6 +2074,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (!Ex.get()->isTypeDependent()) {
// Perform lvalue-to-rvalue cast, if needed.
Ex = DefaultLvalueConversion(Ex.take());
+ if (Ex.isInvalid())
+ return ExprError();
QualType Type = Ex.get()->getType();
@@ -2041,9 +2087,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;
CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
- const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator>
+ Conversions = RD->getVisibleConversionFunctions();
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = I.getDecl();
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
@@ -2323,11 +2371,11 @@ static ExprResult BuildCXXCastArgument(Sema &S,
S.CheckConstructorAccess(CastLoc, Constructor,
InitializedEntity::InitializeTemporary(Ty),
Constructor->getAccess());
-
+
ExprResult Result
= S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
- ConstructorArgs,
- HadMultipleCandidates, /*ZeroInit*/ false,
+ ConstructorArgs, HadMultipleCandidates,
+ /*ListInit*/ false, /*ZeroInit*/ false,
CXXConstructExpr::CK_Complete, SourceRange());
if (Result.isInvalid())
return ExprError();
@@ -2479,14 +2527,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
ToType, SCS.CopyConstructor,
ConstructorArgs,
/*HadMultipleCandidates*/ false,
- /*ZeroInit*/ false,
+ /*ListInit*/ false, /*ZeroInit*/ false,
CXXConstructExpr::CK_Complete,
SourceRange());
}
return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
ToType, SCS.CopyConstructor,
From, /*HadMultipleCandidates*/ false,
- /*ZeroInit*/ false,
+ /*ListInit*/ false, /*ZeroInit*/ false,
CXXConstructExpr::CK_Complete,
SourceRange());
}
@@ -2782,6 +2830,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
break;
}
+ case ICK_Zero_Event_Conversion:
+ From = ImpCastExprToType(From, ToType,
+ CK_ZeroToOCLEvent,
+ From->getValueKind()).take();
+ break;
+
case ICK_Lvalue_To_Rvalue:
case ICK_Array_To_Pointer:
case ICK_Function_To_Pointer:
@@ -2920,10 +2974,13 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
// type due to the overarching C++0x type predicates being implemented
// requiring the complete type.
case UTT_HasNothrowAssign:
+ case UTT_HasNothrowMoveAssign:
case UTT_HasNothrowConstructor:
case UTT_HasNothrowCopy:
case UTT_HasTrivialAssign:
+ case UTT_HasTrivialMoveAssign:
case UTT_HasTrivialDefaultConstructor:
+ case UTT_HasTrivialMoveConstructor:
case UTT_HasTrivialCopy:
case UTT_HasTrivialDestructor:
case UTT_HasVirtualDestructor:
@@ -2942,6 +2999,42 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
llvm_unreachable("Type trait not handled by switch");
}
+static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
+ Sema &Self, SourceLocation KeyLoc, ASTContext &C,
+ bool (CXXRecordDecl::*HasTrivial)() const,
+ bool (CXXRecordDecl::*HasNonTrivial)() const,
+ bool (CXXMethodDecl::*IsDesiredOp)() const)
+{
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)())
+ return true;
+
+ DeclarationName Name = C.DeclarationNames.getCXXOperatorName(Op);
+ DeclarationNameInfo NameInfo(Name, KeyLoc);
+ LookupResult Res(Self, NameInfo, Sema::LookupOrdinaryName);
+ if (Self.LookupQualifiedName(Res, RD)) {
+ bool FoundOperator = false;
+ Res.suppressDiagnostics();
+ for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end();
+ Op != OpEnd; ++Op) {
+ if (isa<FunctionTemplateDecl>(*Op))
+ continue;
+
+ CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
+ if((Operator->*IsDesiredOp)()) {
+ FoundOperator = true;
+ const FunctionProtoType *CPT =
+ Operator->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT || !CPT->isNothrow(Self.Context))
+ return false;
+ }
+ }
+ return FoundOperator;
+ }
+ return false;
+}
+
static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
SourceLocation KeyLoc, QualType T) {
assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
@@ -3060,6 +3153,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
//
// 1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html
// 2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
+ //
+ // Note that these builtins do not behave as documented in g++: if a class
+ // has both a trivial and a non-trivial special member of a particular kind,
+ // they return false! For now, we emulate this behavior.
+ // FIXME: This appears to be a g++ bug: more complex cases reveal that it
+ // does not correctly compute triviality in the presence of multiple special
+ // members of the same kind. Revisit this once the g++ bug is fixed.
case UTT_HasTrivialDefaultConstructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If __is_pod (type) is true then the trait is true, else if type is
@@ -3067,9 +3167,18 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
// constructor ([class.ctor]) then the trait is true, else it is false.
if (T.isPODType(Self.Context))
return true;
- if (const RecordType *RT =
- C.getBaseElementType(T)->getAs<RecordType>())
- return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor();
+ if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
+ return RD->hasTrivialDefaultConstructor() &&
+ !RD->hasNonTrivialDefaultConstructor();
+ return false;
+ case UTT_HasTrivialMoveConstructor:
+ // 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))
+ return true;
+ if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
+ return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor();
return false;
case UTT_HasTrivialCopy:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
@@ -3079,8 +3188,18 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
// is true, else it is false.
if (T.isPODType(Self.Context) || T->isReferenceType())
return true;
- if (const RecordType *RT = T->getAs<RecordType>())
- return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor();
+ if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ return RD->hasTrivialCopyConstructor() &&
+ !RD->hasNonTrivialCopyConstructor();
+ return false;
+ case UTT_HasTrivialMoveAssign:
+ // 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))
+ return true;
+ if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
+ return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment();
return false;
case UTT_HasTrivialAssign:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
@@ -3095,12 +3214,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
// errors if the copy assignment operator is actually used, q.v.
// [class.copy]p12).
- if (C.getBaseElementType(T).isConstQualified())
+ if (T.isConstQualified())
return false;
if (T.isPODType(Self.Context))
return true;
- if (const RecordType *RT = T->getAs<RecordType>())
- return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment();
+ if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ return RD->hasTrivialCopyAssignment() &&
+ !RD->hasNonTrivialCopyAssignment();
return false;
case UTT_HasTrivialDestructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
@@ -3117,9 +3237,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)
return true;
- if (const RecordType *RT =
- C.getBaseElementType(T)->getAs<RecordType>())
- return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
+ if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
+ return RD->hasTrivialDestructor();
return false;
// TODO: Propagate nothrowness for implicitly declared special members.
case UTT_HasNothrowAssign:
@@ -3135,39 +3254,26 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
if (T->isReferenceType())
return false;
if (T.isPODType(Self.Context) || T->isObjCLifetimeType())
- return true;
- if (const RecordType *RT = T->getAs<RecordType>()) {
- CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
- if (RD->hasTrivialCopyAssignment())
- return true;
+ return true;
- bool FoundAssign = false;
- DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
- LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc),
- Sema::LookupOrdinaryName);
- if (Self.LookupQualifiedName(Res, RD)) {
- Res.suppressDiagnostics();
- for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end();
- Op != OpEnd; ++Op) {
- if (isa<FunctionTemplateDecl>(*Op))
- continue;
-
- CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
- if (Operator->isCopyAssignmentOperator()) {
- FoundAssign = true;
- const FunctionProtoType *CPT
- = Operator->getType()->getAs<FunctionProtoType>();
- CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
- if (!CPT)
- return false;
- if (!CPT->isNothrow(Self.Context))
- return false;
- }
- }
- }
-
- return FoundAssign;
- }
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C,
+ &CXXRecordDecl::hasTrivialCopyAssignment,
+ &CXXRecordDecl::hasNonTrivialCopyAssignment,
+ &CXXMethodDecl::isCopyAssignmentOperator);
+ return false;
+ case UTT_HasNothrowMoveAssign:
+ // 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))
+ return true;
+
+ if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>())
+ return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C,
+ &CXXRecordDecl::hasTrivialMoveAssignment,
+ &CXXRecordDecl::hasNonTrivialMoveAssignment,
+ &CXXMethodDecl::isMoveAssignmentOperator);
return false;
case UTT_HasNothrowCopy:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
@@ -3177,16 +3283,16 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
// false.
if (T.isPODType(C) || T->isReferenceType() || T->isObjCLifetimeType())
return true;
- if (const RecordType *RT = T->getAs<RecordType>()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (RD->hasTrivialCopyConstructor())
+ if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
+ if (RD->hasTrivialCopyConstructor() &&
+ !RD->hasNonTrivialCopyConstructor())
return true;
bool FoundConstructor = false;
unsigned FoundTQs;
- DeclContext::lookup_const_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
- Con != ConEnd; ++Con) {
+ DeclContext::lookup_const_result R = Self.LookupConstructors(RD);
+ for (DeclContext::lookup_const_iterator Con = R.begin(),
+ ConEnd = R.end(); Con != ConEnd; ++Con) {
// A template constructor is never a copy constructor.
// FIXME: However, it may actually be selected at the actual overload
// resolution point.
@@ -3218,14 +3324,14 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
// throw an exception then the trait is true, else it is false.
if (T.isPODType(C) || T->isObjCLifetimeType())
return true;
- if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (RD->hasTrivialDefaultConstructor())
+ if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) {
+ if (RD->hasTrivialDefaultConstructor() &&
+ !RD->hasNonTrivialDefaultConstructor())
return true;
- DeclContext::lookup_const_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
- Con != ConEnd; ++Con) {
+ DeclContext::lookup_const_result R = Self.LookupConstructors(RD);
+ for (DeclContext::lookup_const_iterator Con = R.begin(),
+ ConEnd = R.end(); Con != ConEnd; ++Con) {
// FIXME: In C++0x, a constructor template can be a default constructor.
if (isa<FunctionTemplateDecl>(*Con))
continue;
@@ -3247,11 +3353,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If type is a class type with a virtual destructor ([class.dtor])
// then the trait is true, else it is false.
- if (const RecordType *Record = T->getAs<RecordType>()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD))
return Destructor->isVirtual();
- }
return false;
// These type trait expressions are modeled on the specifications for the
@@ -3360,8 +3464,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (SawVoid)
return false;
- llvm::SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs;
- llvm::SmallVector<Expr *, 2> ArgExprs;
+ SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs;
+ SmallVector<Expr *, 2> ArgExprs;
ArgExprs.reserve(Args.size() - 1);
for (unsigned I = 1, N = Args.size(); I != N; ++I) {
QualType T = Args[I]->getType();
@@ -3428,7 +3532,7 @@ ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<ParsedType> Args,
SourceLocation RParenLoc) {
- llvm::SmallVector<TypeSourceInfo *, 4> ConvertedArgs;
+ SmallVector<TypeSourceInfo *, 4> ConvertedArgs;
ConvertedArgs.reserve(Args.size());
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
@@ -4769,7 +4873,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
// a StmtExpr; currently this is only used for asm statements.
// This is hacky, either create a new CXXStmtWithTemporaries statement or
// a new AsmStmtWithTemporaries.
- CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, &SubStmt, 1,
+ CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, SubStmt,
SourceLocation(),
SourceLocation());
Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(),
@@ -4782,8 +4886,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
/// are omitted for the 'topmost' call in the decltype expression. If the
/// topmost call bound a temporary, strip that temporary off the expression.
ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
- ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back();
- assert(Rec.IsDecltype && "not in a decltype expression");
+ assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression");
// C++11 [expr.call]p11:
// If a function call is a prvalue of object type,
@@ -4824,7 +4927,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
E = TopBind->getSubExpr();
// Disable the special decltype handling now.
- Rec.IsDecltype = false;
+ ExprEvalContexts.back().IsDecltype = false;
// In MS mode, don't perform any extra checking of call return types within a
// decltype expression.
@@ -4833,8 +4936,9 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
// Perform the semantic checks we delayed until this point.
CallExpr *TopCall = dyn_cast<CallExpr>(E);
- for (unsigned I = 0, N = Rec.DelayedDecltypeCalls.size(); I != N; ++I) {
- CallExpr *Call = Rec.DelayedDecltypeCalls[I];
+ for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeCalls.size();
+ I != N; ++I) {
+ CallExpr *Call = ExprEvalContexts.back().DelayedDecltypeCalls[I];
if (Call == TopCall)
continue;
@@ -4846,8 +4950,10 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
// Now all relevant types are complete, check the destructors are accessible
// and non-deleted, and annotate them on the temporaries.
- for (unsigned I = 0, N = Rec.DelayedDecltypeBinds.size(); I != N; ++I) {
- CXXBindTemporaryExpr *Bind = Rec.DelayedDecltypeBinds[I];
+ for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeBinds.size();
+ I != N; ++I) {
+ CXXBindTemporaryExpr *Bind =
+ ExprEvalContexts.back().DelayedDecltypeBinds[I];
if (Bind == TopBind)
continue;
@@ -5321,12 +5427,12 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
VK_RValue, OK_Ordinary);
if (HadMultipleCandidates)
ME->setHadMultipleCandidates(true);
+ MarkMemberReferenced(ME);
QualType ResultType = Method->getResultType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
- MarkFunctionReferenced(Exp.get()->getLocStart(), Method);
CXXMemberCallExpr *CE =
new (Context) CXXMemberCallExpr(Context, ME, MultiExprArg(), ResultType, VK,
Exp.get()->getLocEnd());
@@ -5429,7 +5535,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
// normally, we don't need to do anything to handle it, but if it is a
// volatile lvalue with a special form, we perform an lvalue-to-rvalue
// conversion.
- if (getLangOpts().CPlusPlus0x && E->isGLValue() &&
+ if (getLangOpts().CPlusPlus11 && E->isGLValue() &&
E->getType().isVolatileQualified() &&
IsSpecialDiscardedValue(E)) {
ExprResult Res = DefaultLvalueConversion(E);
@@ -5460,7 +5566,9 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
return Owned(E);
}
-ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC) {
+ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
+ bool DiscardedValue,
+ bool IsConstexpr) {
ExprResult FullExpr = Owned(FE);
if (!FullExpr.get())
@@ -5469,24 +5577,25 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC) {
if (DiagnoseUnexpandedParameterPack(FullExpr.get()))
return ExprError();
- // Top-level message sends default to 'id' when we're in a debugger.
- if (getLangOpts().DebuggerCastResultToId &&
- FullExpr.get()->getType() == Context.UnknownAnyTy &&
- isa<ObjCMessageExpr>(FullExpr.get())) {
+ // Top-level expressions default to 'id' when we're in a debugger.
+ if (DiscardedValue && getLangOpts().DebuggerCastResultToId &&
+ FullExpr.get()->getType() == Context.UnknownAnyTy) {
FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType());
if (FullExpr.isInvalid())
return ExprError();
}
-
- FullExpr = CheckPlaceholderExpr(FullExpr.take());
- if (FullExpr.isInvalid())
- return ExprError();
- FullExpr = IgnoredValueConversions(FullExpr.take());
- if (FullExpr.isInvalid())
- return ExprError();
+ if (DiscardedValue) {
+ FullExpr = CheckPlaceholderExpr(FullExpr.take());
+ if (FullExpr.isInvalid())
+ return ExprError();
+
+ FullExpr = IgnoredValueConversions(FullExpr.take());
+ if (FullExpr.isInvalid())
+ return ExprError();
+ }
- CheckImplicitConversions(FullExpr.get(), CC);
+ CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr);
return MaybeCreateExprWithCleanups(FullExpr);
}
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index a7fd47183a16..847db24632b9 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -11,43 +11,32 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
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 llvm::SmallPtrSet<CXXRecordDecl*, 4> &Bases) {
- if (Bases.count(Record->getCanonicalDecl()))
- return false;
-
- RecordDecl *RD = Record->getDefinition();
- if (!RD) return false;
- Record = cast<CXXRecordDecl>(RD);
-
- for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
- E = Record->bases_end(); I != E; ++I) {
- CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
- CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>();
- if (!BaseRT) return false;
-
- CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
- if (!IsProvablyNotDerivedFrom(SemaRef, BaseRecord, Bases))
- return false;
- }
-
- return true;
+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);
}
enum IMAKind {
@@ -111,7 +100,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
// Collect all the declaring classes of instance members we find.
bool hasNonInstance = false;
bool isField = false;
- llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;
+ BaseSet Classes;
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
NamedDecl *D = *I;
@@ -132,7 +121,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
return IMA_Static;
bool IsCXX11UnevaluatedField = false;
- if (SemaRef.getLangOpts().CPlusPlus0x && isField) {
+ if (SemaRef.getLangOpts().CPlusPlus11 && isField) {
// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
@@ -169,16 +158,18 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
// is ill-formed.
if (R.getNamingClass() &&
contextClass->getCanonicalDecl() !=
- R.getNamingClass()->getCanonicalDecl() &&
- contextClass->isProvablyNotDerivedFrom(R.getNamingClass()))
- return hasNonInstance ? IMA_Mixed_Unrelated :
- IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context :
- IMA_Error_Unrelated;
+ R.getNamingClass()->getCanonicalDecl()) {
+ // If the naming class is not the current context, this was a qualified
+ // member name lookup, and it's sufficient to check that we have the naming
+ // class as a base class.
+ Classes.clear();
+ Classes.insert(R.getNamingClass()->getCanonicalDecl());
+ }
// If we can prove that the current context is unrelated to all the
// declaring classes, it can't be an implicit member reference (in
// which case it's an error if any of those members are selected).
- if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes))
+ if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes))
return hasNonInstance ? IMA_Mixed_Unrelated :
IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context :
IMA_Error_Unrelated;
@@ -491,14 +482,14 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
QualType BaseType,
const CXXScopeSpec &SS,
const LookupResult &R) {
- const RecordType *BaseRT = BaseType->getAs<RecordType>();
- if (!BaseRT) {
+ CXXRecordDecl *BaseRecord =
+ cast_or_null<CXXRecordDecl>(computeDeclContext(BaseType));
+ if (!BaseRecord) {
// We can't check this yet because the base type is still
// dependent.
assert(BaseType->isDependentType());
return false;
}
- CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
// If this is an implicit member reference and we find a
@@ -513,11 +504,10 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
if (!DC->isRecord())
continue;
-
- llvm::SmallPtrSet<CXXRecordDecl*,4> MemberRecord;
- MemberRecord.insert(cast<CXXRecordDecl>(DC)->getCanonicalDecl());
- if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord))
+ CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
+ if (BaseRecord->getCanonicalDecl() == MemberRecord ||
+ !BaseRecord->isProvablyNotDerivedFrom(MemberRecord))
return false;
}
@@ -1140,30 +1130,15 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// There's an implicit 'isa' ivar on all objects.
// But we only actually find it this way on objects of type 'id',
// apparently.
- if (OTy->isObjCId() && Member->isStr("isa")) {
- Diag(MemberLoc, diag::warn_objc_isa_use);
+ if (OTy->isObjCId() && Member->isStr("isa"))
return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc,
+ OpLoc,
Context.getObjCClassType()));
- }
-
if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
goto fail;
}
- else if (Member && Member->isStr("isa")) {
- // If an ivar is (1) the first ivar in a root class and (2) named `isa`,
- // then issue the same deprecated warning that id->isa gets.
- ObjCInterfaceDecl *ClassDeclared = 0;
- if (ObjCIvarDecl *IV =
- IDecl->lookupInstanceVariable(Member, ClassDeclared)) {
- if (!ClassDeclared->getSuperClass()
- && (*ClassDeclared->ivar_begin()) == IV) {
- Diag(MemberLoc, diag::warn_objc_isa_use);
- Diag(IV->getLocation(), diag::note_ivar_decl);
- }
- }
- }
if (RequireCompleteType(OpLoc, BaseType, diag::err_typecheck_incomplete_tag,
BaseExpr.get()))
@@ -1269,14 +1244,15 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
if (ObjCMethodDecl *MD = getCurMethodDecl()) {
ObjCMethodFamily MF = MD->getMethodFamily();
warn = (MF != OMF_init && MF != OMF_dealloc &&
- MF != OMF_finalize);
+ MF != OMF_finalize &&
+ !IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
}
if (warn)
Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
}
ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
- MemberLoc,
+ MemberLoc, OpLoc,
BaseExpr.take(),
IsArrow);
@@ -1607,27 +1583,27 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
} else {
QualType BaseType = BaseExpr->getType();
if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType();
-
+
Qualifiers BaseQuals = BaseType.getQualifiers();
-
+
// GC attributes are never picked up by members.
BaseQuals.removeObjCGCAttr();
-
+
// CVR attributes from the base are picked up by members,
// except that 'mutable' members don't pick up 'const'.
if (Field->isMutable()) BaseQuals.removeConst();
-
+
Qualifiers MemberQuals
= S.Context.getCanonicalType(MemberType).getQualifiers();
-
- // TR 18037 does not allow fields to be declared with address spaces.
+
assert(!MemberQuals.hasAddressSpace());
-
+
+
Qualifiers Combined = BaseQuals + MemberQuals;
if (Combined != MemberQuals)
MemberType = S.Context.getQualifiedType(MemberType, Combined);
}
-
+
S.UnusedPrivateFields.remove(Field);
ExprResult Base =
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index e43b6bff5586..e7b5ec9b0168 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -12,20 +12,20 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
-#include "clang/Edit/Rewriters.h"
-#include "clang/Edit/Commit.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
-#include "llvm/ADT/SmallString.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Edit/Commit.h"
+#include "clang/Edit/Rewriters.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "llvm/ADT/SmallString.h"
using namespace clang;
using namespace sema;
@@ -170,9 +170,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
QualType NumberType,
bool isLiteral = false,
SourceRange R = SourceRange()) {
- llvm::Optional<NSAPI::NSNumberLiteralMethodKind> Kind
- = S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType);
-
+ Optional<NSAPI::NSNumberLiteralMethodKind> Kind =
+ S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType);
+
if (!Kind) {
if (isLiteral) {
S.Diag(Loc, diag::err_invalid_nsnumber_type)
@@ -238,7 +238,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
SourceLocation(), SourceLocation(),
&CX.Idents.get("value"),
NumberType, /*TInfo=*/0, SC_None,
- SC_None, 0);
+ 0);
Method->setMethodParams(S.Context, value, ArrayRef<SourceLocation>());
}
@@ -489,7 +489,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
&Context.Idents.get("value"),
Context.getPointerType(ConstCharType),
/*TInfo=*/0,
- SC_None, SC_None, 0);
+ SC_None, 0);
M->setMethodParams(Context, value, ArrayRef<SourceLocation>());
BoxingMethod = M;
}
@@ -656,16 +656,14 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(objects);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(cnt);
Method->setMethodParams(Context, Params, ArrayRef<SourceLocation>());
}
@@ -774,24 +772,21 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(objects);
ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("keys"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(keys);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(cnt);
Method->setMethodParams(Context, Params, ArrayRef<SourceLocation>());
}
@@ -981,7 +976,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
llvm::DenseMap<Selector, SourceLocation>::iterator Pos
= ReferencedSelectors.find(Sel);
if (Pos == ReferencedSelectors.end())
- ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
+ ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));
}
// In ARC, forbid the user from using @selector for
@@ -1094,6 +1089,73 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType,
return ReceiverType;
}
+/// Look for an ObjC method whose result type exactly matches the given type.
+static const ObjCMethodDecl *
+findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
+ QualType instancetype) {
+ if (MD->getResultType() == instancetype) return MD;
+
+ // For these purposes, a method in an @implementation overrides a
+ // declaration in the @interface.
+ if (const ObjCImplDecl *impl =
+ dyn_cast<ObjCImplDecl>(MD->getDeclContext())) {
+ const ObjCContainerDecl *iface;
+ if (const ObjCCategoryImplDecl *catImpl =
+ dyn_cast<ObjCCategoryImplDecl>(impl)) {
+ iface = catImpl->getCategoryDecl();
+ } else {
+ iface = impl->getClassInterface();
+ }
+
+ const ObjCMethodDecl *ifaceMD =
+ iface->getMethod(MD->getSelector(), MD->isInstanceMethod());
+ if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype);
+ }
+
+ SmallVector<const ObjCMethodDecl *, 4> overrides;
+ MD->getOverriddenMethods(overrides);
+ for (unsigned i = 0, e = overrides.size(); i != e; ++i) {
+ if (const ObjCMethodDecl *result =
+ findExplicitInstancetypeDeclarer(overrides[i], instancetype))
+ return result;
+ }
+
+ return 0;
+}
+
+void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
+ // Only complain if we're in an ObjC method and the required return
+ // type doesn't match the method's declared return type.
+ ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext);
+ if (!MD || !MD->hasRelatedResultType() ||
+ Context.hasSameUnqualifiedType(destType, MD->getResultType()))
+ return;
+
+ // Look for a method overridden by this method which explicitly uses
+ // 'instancetype'.
+ if (const ObjCMethodDecl *overridden =
+ findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {
+ SourceLocation loc;
+ SourceRange range;
+ if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) {
+ range = TSI->getTypeLoc().getSourceRange();
+ loc = range.getBegin();
+ }
+ if (loc.isInvalid())
+ loc = overridden->getLocation();
+ Diag(loc, diag::note_related_result_type_explicit)
+ << /*current method*/ 1 << range;
+ return;
+ }
+
+ // Otherwise, if we have an interesting method family, note that.
+ // This should always trigger if the above didn't.
+ if (ObjCMethodFamily family = MD->getMethodFamily())
+ Diag(MD->getLocation(), diag::note_related_result_type_family)
+ << /*current method*/ 1
+ << family;
+}
+
void Sema::EmitRelatedResultTypeNote(const Expr *E) {
E = E->IgnoreParenImpCasts();
const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);
@@ -1135,10 +1197,16 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
if (Args[i]->isTypeDependent())
continue;
- ExprResult Result = DefaultArgumentPromotion(Args[i]);
- if (Result.isInvalid())
+ ExprResult result;
+ if (getLangOpts().DebuggerSupport) {
+ QualType paramTy; // ignored
+ result = checkUnknownAnyArg(lbrac, Args[i], paramTy);
+ } else {
+ result = DefaultArgumentPromotion(Args[i]);
+ }
+ if (result.isInvalid())
return true;
- Args[i] = Result.take();
+ Args[i] = result.take();
}
unsigned DiagID;
@@ -1196,6 +1264,22 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
!param->hasAttr<CFConsumedAttr>())
argExpr = stripARCUnbridgedCast(argExpr);
+ // If the parameter is __unknown_anytype, infer its type
+ // from the argument.
+ if (param->getType() == Context.UnknownAnyTy) {
+ QualType paramType;
+ ExprResult argE = checkUnknownAnyArg(lbrac, argExpr, paramType);
+ if (argE.isInvalid()) {
+ IsError = true;
+ } else {
+ Args[i] = argE.take();
+
+ // Update the parameter type in-place.
+ param->setType(paramType);
+ }
+ continue;
+ }
+
if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
param->getType(),
diag::err_call_incomplete_argument, argExpr))
@@ -1539,8 +1623,15 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) {
if (CurMethod->isInstanceMethod()) {
- QualType T =
- Context.getObjCInterfaceType(CurMethod->getClassInterface());
+ ObjCInterfaceDecl *Super =
+ CurMethod->getClassInterface()->getSuperClass();
+ if (!Super) {
+ // The current class does not have a superclass.
+ Diag(receiverNameLoc, diag::error_root_class_cannot_use_super)
+ << CurMethod->getClassInterface()->getIdentifier();
+ return ExprError();
+ }
+ QualType T = Context.getObjCInterfaceType(Super);
T = Context.getObjCObjectPointerType(T);
return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
@@ -1695,9 +1786,11 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
QualType T;
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))
T = Context.getObjCInterfaceType(Class);
- else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+ else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) {
T = Context.getTypeDeclType(Type);
- else
+ DiagnoseUseOfDecl(Type, NameLoc);
+ }
+ else
return ObjCInstanceMessage;
// We have a class message, and T is the type we're
@@ -2106,8 +2199,46 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
return ExprError();
Receiver = Result.take();
ReceiverType = Receiver->getType();
+
+ // If the receiver is an ObjC pointer, a block pointer, or an
+ // __attribute__((NSObject)) pointer, we don't need to do any
+ // special conversion in order to look up a receiver.
+ if (ReceiverType->isObjCRetainableType()) {
+ // do nothing
+ } else if (!getLangOpts().ObjCAutoRefCount &&
+ !Context.getObjCIdType().isNull() &&
+ (ReceiverType->isPointerType() ||
+ ReceiverType->isIntegerType())) {
+ // Implicitly convert integers and pointers to 'id' but emit a warning.
+ // But not in ARC.
+ Diag(Loc, diag::warn_bad_receiver_type)
+ << ReceiverType
+ << Receiver->getSourceRange();
+ if (ReceiverType->isPointerType()) {
+ Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ CK_CPointerToObjCPointerCast).take();
+ } else {
+ // TODO: specialized warning on null receivers?
+ bool IsNull = Receiver->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull);
+ CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;
+ Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ Kind).take();
+ }
+ ReceiverType = Receiver->getType();
+ } else if (getLangOpts().CPlusPlus) {
+ ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver);
+ if (result.isUsable()) {
+ Receiver = result.take();
+ ReceiverType = Receiver->getType();
+ }
+ }
}
+ // There's a somewhat weird interaction here where we assume that we
+ // won't actually have a method unless we also don't need to do some
+ // of the more detailed type-checking on the receiver.
+
if (!Method) {
// Handle messages to id.
bool receiverIsId = ReceiverType->isObjCIdType();
@@ -2223,7 +2354,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (!Method && getLangOpts().ObjCAutoRefCount) {
Diag(Loc, diag::err_arc_may_not_respond)
- << OCIType->getPointeeType() << Sel;
+ << OCIType->getPointeeType() << Sel
+ << SourceRange(SelectorLocs.front(), SelectorLocs.back());
return ExprError();
}
@@ -2242,48 +2374,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass))
return ExprError();
- } else if (!getLangOpts().ObjCAutoRefCount &&
- !Context.getObjCIdType().isNull() &&
- (ReceiverType->isPointerType() ||
- ReceiverType->isIntegerType())) {
- // Implicitly convert integers and pointers to 'id' but emit a warning.
- // But not in ARC.
- Diag(Loc, diag::warn_bad_receiver_type)
- << ReceiverType
- << Receiver->getSourceRange();
- if (ReceiverType->isPointerType())
- Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
- CK_CPointerToObjCPointerCast).take();
- else {
- // TODO: specialized warning on null receivers?
- bool IsNull = Receiver->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull);
- CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;
- Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
- Kind).take();
- }
- ReceiverType = Receiver->getType();
} else {
- ExprResult ReceiverRes;
- if (getLangOpts().CPlusPlus)
- ReceiverRes = PerformContextuallyConvertToObjCPointer(Receiver);
- if (ReceiverRes.isUsable()) {
- Receiver = ReceiverRes.take();
- return BuildInstanceMessage(Receiver,
- ReceiverType,
- SuperLoc,
- Sel,
- Method,
- LBracLoc,
- SelectorLocs,
- RBracLoc,
- ArgsIn);
- } else {
- // Reject other random receiver types (e.g. structs).
- Diag(Loc, diag::err_bad_receiver_type)
- << ReceiverType << Receiver->getSourceRange();
- return ExprError();
- }
+ // Reject other random receiver types (e.g. structs).
+ Diag(Loc, diag::err_bad_receiver_type)
+ << ReceiverType << Receiver->getSourceRange();
+ return ExprError();
}
}
}
@@ -2447,6 +2542,18 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
return MaybeBindToTemporary(Result);
}
+static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) {
+ if (ObjCSelectorExpr *OSE =
+ dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) {
+ Selector Sel = OSE->getSelector();
+ SourceLocation Loc = OSE->getAtLoc();
+ llvm::DenseMap<Selector, SourceLocation>::iterator Pos
+ = S.ReferencedSelectors.find(Sel);
+ if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)
+ S.ReferencedSelectors.erase(Pos);
+ }
+}
+
// ActOnInstanceMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
@@ -2460,6 +2567,20 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S,
if (!Receiver)
return ExprError();
+ // A ParenListExpr can show up while doing error recovery with invalid code.
+ if (isa<ParenListExpr>(Receiver)) {
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver);
+ if (Result.isInvalid()) return ExprError();
+ Receiver = Result.take();
+ }
+
+ if (RespondsToSelectorSel.isNull()) {
+ IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector");
+ RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId);
+ }
+ if (Sel == RespondsToSelectorSel)
+ RemoveSelectorFromWarningCache(*this, Args[0]);
+
return BuildInstanceMessage(Receiver, Receiver->getType(),
/*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
LBracLoc, SelectorLocs, RBracLoc, Args);
@@ -2770,19 +2891,36 @@ static void addFixitForObjCARCConversion(Sema &S,
SourceLocation afterLParen,
QualType castType,
Expr *castExpr,
+ Expr *realCast,
const char *bridgeKeyword,
const char *CFBridgeName) {
// We handle C-style and implicit casts here.
switch (CCK) {
case Sema::CCK_ImplicitConversion:
case Sema::CCK_CStyleCast:
+ case Sema::CCK_OtherCast:
break;
case Sema::CCK_FunctionalCast:
- case Sema::CCK_OtherCast:
return;
}
if (CFBridgeName) {
+ if (CCK == Sema::CCK_OtherCast) {
+ if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {
+ SourceRange range(NCE->getOperatorLoc(),
+ NCE->getAngleBrackets().getEnd());
+ SmallString<32> BridgeCall;
+
+ SourceManager &SM = S.getSourceManager();
+ char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));
+ if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts()))
+ BridgeCall += ' ';
+
+ BridgeCall += CFBridgeName;
+ DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall));
+ }
+ return;
+ }
Expr *castedE = castExpr;
if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE))
castedE = CCE->getSubExpr();
@@ -2814,6 +2952,16 @@ static void addFixitForObjCARCConversion(Sema &S,
if (CCK == Sema::CCK_CStyleCast) {
DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword));
+ } else if (CCK == Sema::CCK_OtherCast) {
+ if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {
+ std::string castCode = "(";
+ castCode += bridgeKeyword;
+ castCode += castType.getAsString();
+ castCode += ")";
+ SourceRange Range(NCE->getOperatorLoc(),
+ NCE->getAngleBrackets().getEnd());
+ DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode));
+ }
} else {
std::string castCode = "(";
castCode += bridgeKeyword;
@@ -2838,7 +2986,8 @@ static void addFixitForObjCARCConversion(Sema &S,
static void
diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
QualType castType, ARCConversionTypeClass castACTC,
- Expr *castExpr, ARCConversionTypeClass exprACTC,
+ Expr *castExpr, Expr *realCast,
+ ARCConversionTypeClass exprACTC,
Sema::CheckedConversionKind CCK) {
SourceLocation loc =
(castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
@@ -2885,17 +3034,24 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
if (CreateRule != ACC_plusOne)
{
- DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge);
+ DiagnosticBuilder DiagB =
+ (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
+ : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
- castType, castExpr, "__bridge ", 0);
+ castType, castExpr, realCast, "__bridge ", 0);
}
if (CreateRule != ACC_plusZero)
{
- DiagnosticBuilder DiagB = S.Diag(br ? castExpr->getExprLoc() : noteLoc,
- diag::note_arc_bridge_transfer)
- << castExprType << br;
+ DiagnosticBuilder DiagB =
+ (CCK == Sema::CCK_OtherCast && !br) ?
+ S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) << castExprType :
+ S.Diag(br ? castExpr->getExprLoc() : noteLoc,
+ diag::note_arc_bridge_transfer)
+ << castExprType << br;
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
- castType, castExpr, "__bridge_transfer ",
+ castType, castExpr, realCast, "__bridge_transfer ",
br ? "CFBridgingRelease" : 0);
}
@@ -2918,17 +3074,23 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
if (CreateRule != ACC_plusOne)
{
- DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge);
+ DiagnosticBuilder DiagB =
+ (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
+ : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
- castType, castExpr, "__bridge ", 0);
+ castType, castExpr, realCast, "__bridge ", 0);
}
if (CreateRule != ACC_plusZero)
{
- DiagnosticBuilder DiagB = S.Diag(br ? castExpr->getExprLoc() : noteLoc,
- diag::note_arc_bridge_retained)
- << castType << br;
+ DiagnosticBuilder DiagB =
+ (CCK == Sema::CCK_OtherCast && !br) ?
+ S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) << castType :
+ S.Diag(br ? castExpr->getExprLoc() : noteLoc,
+ diag::note_arc_bridge_retained)
+ << castType << br;
+
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
- castType, castExpr, "__bridge_retained ",
+ castType, castExpr, realCast, "__bridge_retained ",
br ? "CFBridgingRetain" : 0);
}
@@ -3025,7 +3187,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
return ACR_unbridged;
diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
- castExpr, exprACTC, CCK);
+ castExpr, castExpr, exprACTC, CCK);
return ACR_okay;
}
@@ -3060,7 +3222,7 @@ void Sema::diagnoseARCUnbridgedCast(Expr *e) {
assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);
diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
- castExpr, ACTC_retainable, CCK);
+ castExpr, realCast, ACTC_retainable, CCK);
}
/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast
diff --git a/lib/Sema/SemaFixItUtils.cpp b/lib/Sema/SemaFixItUtils.cpp
index b61b9307dde9..2a845ba9898b 100644
--- a/lib/Sema/SemaFixItUtils.cpp
+++ b/lib/Sema/SemaFixItUtils.cpp
@@ -178,7 +178,7 @@ static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S)
if (T.isBooleanType() && S.LangOpts.CPlusPlus)
return "false";
if (T.isPointerType() || T.isMemberPointerType()) {
- if (S.LangOpts.CPlusPlus0x)
+ if (S.LangOpts.CPlusPlus11)
return "nullptr";
if (isMacroDefined(S, "NULL"))
return "NULL";
@@ -205,7 +205,7 @@ std::string Sema::getFixItZeroInitializerForType(QualType T) const {
const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
if (!RD || !RD->hasDefinition())
return std::string();
- if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor())
+ if (LangOpts.CPlusPlus11 && !RD->hasUserProvidedDefaultConstructor())
return "{}";
if (RD->isAggregate())
return " = {}";
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 3596bbfc725a..63309e376eac 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -11,16 +11,16 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/Designator.h"
#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/SemaInternal.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
@@ -901,11 +901,11 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
if (Index >= IList->getNumInits()) {
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(),
- SemaRef.getLangOpts().CPlusPlus0x ?
+ SemaRef.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_empty_scalar_initializer :
diag::err_empty_scalar_initializer)
<< IList->getSourceRange();
- hadError = !SemaRef.getLangOpts().CPlusPlus0x;
+ hadError = !SemaRef.getLangOpts().CPlusPlus11;
++Index;
++StructuredIndex;
return;
@@ -985,7 +985,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
}
Expr *expr = IList->getInit(Index);
- if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus0x) {
+ if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus11) {
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
<< DeclType << IList->getSourceRange();
@@ -1632,8 +1632,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
StructuredList = IsFirstDesignator? SyntacticToSemantic.lookup(IList)
: getStructuredSubobjectInit(IList, Index, CurrentObjectType,
StructuredList, StructuredIndex,
- SourceRange(D->getStartLocation(),
- DIE->getSourceRange().getEnd()));
+ SourceRange(D->getLocStart(),
+ DIE->getLocEnd()));
assert(StructuredList && "Expected a structured initializer list");
}
@@ -1706,7 +1706,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// struct/union.
DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
FieldDecl *ReplacementField = 0;
- if (Lookup.first == Lookup.second) {
+ if (Lookup.empty()) {
// Name lookup didn't find anything. Determine whether this
// was a typo for another field name.
FieldInitializerValidatorCCC Validator(RT->getDecl());
@@ -1739,7 +1739,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Name lookup found something, but it wasn't a field.
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
<< FieldName;
- SemaRef.Diag((*Lookup.first)->getLocation(),
+ SemaRef.Diag(Lookup.front()->getLocation(),
diag::note_field_designator_found);
++Index;
return true;
@@ -1801,10 +1801,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (!VerifyOnly) {
DesignatedInitExpr::Designator *NextD
= DIE->getDesignator(DesigIdx + 1);
- SemaRef.Diag(NextD->getStartLocation(),
+ SemaRef.Diag(NextD->getLocStart(),
diag::err_designator_into_flexible_array_member)
- << SourceRange(NextD->getStartLocation(),
- DIE->getSourceRange().getEnd());
+ << SourceRange(NextD->getLocStart(),
+ DIE->getLocEnd());
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
<< *Field;
}
@@ -2424,6 +2424,8 @@ void InitializationSequence::Step::Destroy() {
case SK_PassByIndirectRestore:
case SK_ProduceObjCObject:
case SK_StdInitializerList:
+ case SK_OCLSamplerInit:
+ case SK_OCLZeroEvent:
break;
case SK_ConversionSequence:
@@ -2652,6 +2654,20 @@ void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddOCLSamplerInitStep(QualType T) {
+ Step S;
+ S.Kind = SK_OCLSamplerInit;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddOCLZeroEventStep(QualType T) {
+ Step S;
+ S.Kind = SK_OCLZeroEvent;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::RewrapReferenceInitList(QualType T,
InitListExpr *Syntactic) {
assert(Syntactic->getNumInits() == 1 &&
@@ -2744,14 +2760,14 @@ static OverloadingResult
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
- DeclContext::lookup_iterator Con,
- DeclContext::lookup_iterator ConEnd,
+ ArrayRef<NamedDecl *> Ctors,
OverloadCandidateSet::iterator &Best,
bool CopyInitializing, bool AllowExplicit,
bool OnlyListConstructors, bool InitListSyntax) {
CandidateSet.clear();
- for (; Con != ConEnd; ++Con) {
+ for (ArrayRef<NamedDecl *>::iterator
+ Con = Ctors.begin(), ConEnd = Ctors.end(); Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
bool SuppressUserConversions = false;
@@ -2842,8 +2858,11 @@ static void TryConstructorInitialization(Sema &S,
// - Otherwise, if T is a class type, constructors are considered. The
// applicable constructors are enumerated, and the best one is chosen
// through overload resolution.
- DeclContext::lookup_iterator ConStart, ConEnd;
- llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl);
+ DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl);
+ // The container holding the constructors can under certain conditions
+ // be changed while iterating (e.g. because of deserialization).
+ // To be safe we copy the lookup results to a new container.
+ SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
OverloadingResult Result = OR_No_Viable_Function;
OverloadCandidateSet::iterator Best;
@@ -2861,11 +2880,9 @@ static void TryConstructorInitialization(Sema &S,
// If the initializer list has no elements and T has a default constructor,
// the first phase is omitted.
- if (ILE->getNumInits() != 0 ||
- (!DestRecordDecl->hasDeclaredDefaultConstructor() &&
- !DestRecordDecl->needsImplicitDefaultConstructor()))
+ if (ILE->getNumInits() != 0 || !DestRecordDecl->hasDefaultConstructor())
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
- CandidateSet, ConStart, ConEnd, Best,
+ CandidateSet, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructor=*/true,
InitListSyntax);
@@ -2883,7 +2900,7 @@ static void TryConstructorInitialization(Sema &S,
if (Result == OR_No_Viable_Function) {
AsInitializerList = false;
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
- CandidateSet, ConStart, ConEnd, Best,
+ CandidateSet, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructors=*/false,
InitListSyntax);
@@ -2983,7 +3000,7 @@ static void TryReferenceListInitialization(Sema &S,
InitializationSequence &Sequence)
{
// First, catch C++03 where this isn't possible.
- if (!S.getLangOpts().CPlusPlus0x) {
+ if (!S.getLangOpts().CPlusPlus11) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
return;
}
@@ -3023,6 +3040,10 @@ static void TryReferenceListInitialization(Sema &S,
Sequence.RewrapReferenceInitList(cv1T1, InitList);
return;
}
+
+ // Update the initializer if we've resolved an overloaded function.
+ if (Sequence.step_begin() != Sequence.step_end())
+ Sequence.RewrapReferenceInitList(cv1T1, InitList);
}
// Not reference-related. Create a temporary and bind to that.
@@ -3067,14 +3088,13 @@ static void TryListInitialization(Sema &S,
// C++11 [dcl.init.list]p3:
// - If T is an aggregate, aggregate initialization is performed.
if (!DestType->isAggregateType()) {
- if (S.getLangOpts().CPlusPlus0x) {
+ 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
// value-initialized.
if (InitList->getNumInits() == 0) {
CXXRecordDecl *RD = DestType->getAsCXXRecordDecl();
- if (RD->hasDeclaredDefaultConstructor() ||
- RD->needsImplicitDefaultConstructor()) {
+ if (RD->hasDefaultConstructor()) {
TryValueInitialization(S, Entity, Kind, Sequence, InitList);
return;
}
@@ -3099,7 +3119,7 @@ static void TryListInitialization(Sema &S,
InitListChecker CheckInitList(S, Entity, InitList,
DestType, /*VerifyOnly=*/true,
Kind.getKind() != InitializationKind::IK_DirectList ||
- !S.getLangOpts().CPlusPlus0x);
+ !S.getLangOpts().CPlusPlus11);
if (CheckInitList.HadError()) {
Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
return;
@@ -3152,10 +3172,14 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// to see if there is a suitable conversion.
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
- DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
- Con != ConEnd; ++Con) {
- NamedDecl *D = *Con;
+ DeclContext::lookup_result R = S.LookupConstructors(T1RecordDecl);
+ // The container holding the constructors can under certain conditions
+ // be changed while iterating (e.g. because of deserialization).
+ // To be safe we copy the lookup results to a new container.
+ SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
+ for (SmallVector<NamedDecl*, 16>::iterator
+ CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
+ NamedDecl *D = *CI;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
@@ -3191,10 +3215,11 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// functions.
CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
- const UnresolvedSetImpl *Conversions
- = T2RecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator>
+ Conversions = T2RecordDecl->getVisibleConversionFunctions();
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -3237,10 +3262,9 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
return Result;
FunctionDecl *Function = Best->Function;
-
- // This is the overload that will actually be used for the initialization, so
- // mark it as used.
- S.MarkFunctionReferenced(DeclLoc, Function);
+ // This is the overload that will be used for this initialization step if we
+ // use this initialization. Mark it as referenced.
+ Function->setReferenced();
// Compute the returned type of the conversion.
if (isa<CXXConversionDecl>(Function))
@@ -3456,9 +3480,9 @@ static void TryReferenceInitializationCore(Sema &S,
//
// The constructor that would be used to make the copy shall
// be callable whether or not the copy is actually done.
- if (!S.getLangOpts().CPlusPlus0x && !S.getLangOpts().MicrosoftExt)
+ if (!S.getLangOpts().CPlusPlus11 && !S.getLangOpts().MicrosoftExt)
Sequence.AddExtraneousCopyToTemporary(cv2T2);
- else if (S.getLangOpts().CPlusPlus0x)
+ else if (S.getLangOpts().CPlusPlus11)
CheckCXX98CompatAccessibleCopy(S, Entity, Initializer);
}
@@ -3494,6 +3518,14 @@ static void TryReferenceInitializationCore(Sema &S,
return;
}
+ if ((RefRelationship == Sema::Ref_Compatible ||
+ RefRelationship == Sema::Ref_Compatible_With_Added_Qualification) &&
+ isRValueRef && InitCategory.isLValue()) {
+ Sequence.SetFailed(
+ InitializationSequence::FK_RValueReferenceBindingToLValue);
+ return;
+ }
+
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
return;
}
@@ -3589,7 +3621,7 @@ static void TryValueInitialization(Sema &S,
if (const RecordType *RT = T->getAs<RecordType>()) {
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
bool NeedZeroInitialization = true;
- if (!S.getLangOpts().CPlusPlus0x) {
+ if (!S.getLangOpts().CPlusPlus11) {
// C++98:
// -- if T is a class type (clause 9) with a user-declared constructor
// (12.1), then the default constructor for T is called (and the
@@ -3616,6 +3648,22 @@ static void TryValueInitialization(Sema &S,
if (NeedZeroInitialization)
Sequence.AddZeroInitializationStep(Entity.getType());
+ // C++03:
+ // -- if T is a non-union class type without a user-declared constructor,
+ // then every non-static data member and base class component of T is
+ // value-initialized;
+ // [...] A program that calls for [...] value-initialization of an
+ // entity of reference type is ill-formed.
+ //
+ // C++11 doesn't need this handling, because value-initialization does not
+ // occur recursively there, and the implicit default constructor is
+ // defined as deleted in the problematic cases.
+ if (!S.getLangOpts().CPlusPlus11 &&
+ ClassDecl->hasUninitializedReferenceMember()) {
+ Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference);
+ return;
+ }
+
// If this is list-value-initialization, pass the empty init list on when
// building the constructor call. This affects the semantics of a few
// things (such as whether an explicit default constructor can be called).
@@ -3700,12 +3748,11 @@ static void TryUserDefinedConversion(Sema &S,
// Try to complete the type we're converting to.
if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
- DeclContext::lookup_iterator ConOrig, ConEndOrig;
- llvm::tie(ConOrig, ConEndOrig) = S.LookupConstructors(DestRecordDecl);
+ 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
// to a new container.
- SmallVector<NamedDecl*, 8> CopyOfCon(ConOrig, ConEndOrig);
+ SmallVector<NamedDecl*, 8> CopyOfCon(R.begin(), R.end());
for (SmallVector<NamedDecl*, 8>::iterator
Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end();
Con != ConEnd; ++Con) {
@@ -3750,11 +3797,11 @@ static void TryUserDefinedConversion(Sema &S,
CXXRecordDecl *SourceRecordDecl
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
- const UnresolvedSetImpl *Conversions
- = SourceRecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
- E = Conversions->end();
- I != E; ++I) {
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator>
+ Conversions = SourceRecordDecl->getVisibleConversionFunctions();
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -3791,7 +3838,7 @@ static void TryUserDefinedConversion(Sema &S,
}
FunctionDecl *Function = Best->Function;
- S.MarkFunctionReferenced(DeclLoc, Function);
+ Function->setReferenced();
bool HadMultipleCandidates = (CandidateSet.size() > 1);
if (isa<CXXConstructorDecl>(Function)) {
@@ -3837,14 +3884,15 @@ enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar };
/// Determines whether this expression is an acceptable ICR source.
static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
- bool isAddressOf) {
+ bool isAddressOf, bool &isWeakAccess) {
// Skip parens.
e = e->IgnoreParens();
// Skip address-of nodes.
if (UnaryOperator *op = dyn_cast<UnaryOperator>(e)) {
if (op->getOpcode() == UO_AddrOf)
- return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true);
+ return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true,
+ isWeakAccess);
// Skip certain casts.
} else if (CastExpr *ce = dyn_cast<CastExpr>(e)) {
@@ -3853,7 +3901,7 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
case CK_BitCast:
case CK_LValueBitCast:
case CK_NoOp:
- return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf);
+ return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf, isWeakAccess);
case CK_ArrayToPointerDecay:
return IIK_nonscalar;
@@ -3867,6 +3915,11 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
// If we have a declaration reference, it had better be a local variable.
} else if (isa<DeclRefExpr>(e)) {
+ // set isWeakAccess to true, to mean that there will be an implicit
+ // load which requires a cleanup.
+ if (e->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
+ isWeakAccess = true;
+
if (!isAddressOf) return IIK_nonlocal;
VarDecl *var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl());
@@ -3876,10 +3929,11 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
// If we have a conditional operator, check both sides.
} else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) {
- if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf))
+ if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf,
+ isWeakAccess))
return iik;
- return isInvalidICRSource(C, cond->getRHS(), isAddressOf);
+ return isInvalidICRSource(C, cond->getRHS(), isAddressOf, isWeakAccess);
// These are never scalar.
} else if (isa<ArraySubscriptExpr>(e)) {
@@ -3898,8 +3952,13 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
/// indirect copy/restore.
static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
assert(src->isRValue());
-
- InvalidICRKind iik = isInvalidICRSource(S.Context, src, false);
+ bool isWeakAccess = false;
+ InvalidICRKind iik = isInvalidICRSource(S.Context, src, false, isWeakAccess);
+ // If isWeakAccess to true, there will be an implicit
+ // load which requires a cleanup.
+ if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess)
+ S.ExprNeedsCleanups = true;
+
if (iik == IIK_okay) return;
S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback)
@@ -3973,6 +4032,39 @@ static bool tryObjCWritebackConversion(Sema &S,
return true;
}
+static bool TryOCLSamplerInitialization(Sema &S,
+ InitializationSequence &Sequence,
+ QualType DestType,
+ Expr *Initializer) {
+ if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() ||
+ !Initializer->isIntegerConstantExpr(S.getASTContext()))
+ return false;
+
+ Sequence.AddOCLSamplerInitStep(DestType);
+ return true;
+}
+
+//
+// OpenCL 1.2 spec, s6.12.10
+//
+// The event argument can also be used to associate the
+// async_work_group_copy with a previous async copy allowing
+// an event to be shared by multiple async copies; otherwise
+// event should be zero.
+//
+static bool TryOCLZeroEventInitialization(Sema &S,
+ InitializationSequence &Sequence,
+ QualType DestType,
+ Expr *Initializer) {
+ if (!S.getLangOpts().OpenCL || !DestType->isEventT() ||
+ !Initializer->isIntegerConstantExpr(S.getASTContext()) ||
+ (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0))
+ return false;
+
+ Sequence.AddOCLZeroEventStep(DestType);
+ return true;
+}
+
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4115,7 +4207,13 @@ InitializationSequence::InitializationSequence(Sema &S,
tryObjCWritebackConversion(S, *this, Entity, Initializer)) {
return;
}
-
+
+ if (TryOCLSamplerInitialization(S, *this, DestType, Initializer))
+ return;
+
+ if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer))
+ return;
+
// Handle initialization in C
AddCAssignmentStep(DestType);
MaybeProduceObjCObject(S, *this, Entity);
@@ -4258,7 +4356,7 @@ getAssignmentAction(const InitializedEntity &Entity) {
llvm_unreachable("Invalid EntityKind!");
}
-/// \brief Whether we should binding a created object as a temporary when
+/// \brief Whether we should bind a created object as a temporary when
/// initializing the given entity.
static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
@@ -4288,7 +4386,6 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
/// created for that initialization, requires destruction.
static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
- case InitializedEntity::EK_Member:
case InitializedEntity::EK_Result:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
@@ -4299,6 +4396,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_LambdaCapture:
return false;
+ case InitializedEntity::EK_Member:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Temporary:
@@ -4316,12 +4414,17 @@ static void LookupCopyAndMoveConstructors(Sema &S,
OverloadCandidateSet &CandidateSet,
CXXRecordDecl *Class,
Expr *CurInitExpr) {
- DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
- Con != ConEnd; ++Con) {
+ DeclContext::lookup_result R = S.LookupConstructors(Class);
+ // The container holding the constructors can under certain conditions
+ // be changed while iterating (e.g. because of deserialization).
+ // To be safe we copy the lookup results to a new container.
+ SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
+ for (SmallVector<NamedDecl*, 16>::iterator
+ CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
+ NamedDecl *D = *CI;
CXXConstructorDecl *Constructor = 0;
- if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) {
+ if ((Constructor = dyn_cast<CXXConstructorDecl>(D))) {
// Handle copy/moveconstructors, only.
if (!Constructor || Constructor->isInvalidDecl() ||
!Constructor->isCopyOrMoveConstructor() ||
@@ -4336,7 +4439,7 @@ static void LookupCopyAndMoveConstructors(Sema &S,
}
// Handle constructor templates.
- FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con);
+ FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl->isInvalidDecl())
continue;
@@ -4513,8 +4616,6 @@ static ExprResult CopyObject(Sema &S,
return S.Owned(CurInitExpr);
}
- S.MarkFunctionReferenced(Loc, Constructor);
-
// Determine the arguments required to actually perform the
// constructor call (we might have derived-to-base conversions, or
// the copy constructor may have default arguments).
@@ -4526,6 +4627,7 @@ static ExprResult CopyObject(Sema &S,
CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
ConstructorArgs,
HadMultipleCandidates,
+ /*ListInit*/ false,
/*ZeroInit*/ false,
CXXConstructExpr::CK_Complete,
SourceRange());
@@ -4542,7 +4644,7 @@ static ExprResult CopyObject(Sema &S,
static void CheckCXX98CompatAccessibleCopy(Sema &S,
const InitializedEntity &Entity,
Expr *CurInitExpr) {
- assert(S.getLangOpts().CPlusPlus0x);
+ assert(S.getLangOpts().CPlusPlus11);
const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>();
if (!Record)
@@ -4615,7 +4717,8 @@ PerformConstructorInitialization(Sema &S,
const InitializationKind &Kind,
MultiExprArg Args,
const InitializationSequence::Step& Step,
- bool &ConstructorInitRequiresZeroInit) {
+ bool &ConstructorInitRequiresZeroInit,
+ bool IsListInitialization) {
unsigned NumArgs = Args.size();
CXXConstructorDecl *Constructor
= cast<CXXConstructorDecl>(Step.Function.Function);
@@ -4653,7 +4756,8 @@ PerformConstructorInitialization(Sema &S,
// call.
if (S.CompleteConstructorCall(Constructor, Args,
Loc, ConstructorArgs,
- AllowExplicitConv))
+ AllowExplicitConv,
+ IsListInitialization))
return ExprError();
@@ -4673,13 +4777,12 @@ PerformConstructorInitialization(Sema &S,
if (Kind.getKind() != InitializationKind::IK_DirectList)
ParenRange = Kind.getParenRange();
- CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
- Constructor,
- TSInfo,
- ConstructorArgs,
- ParenRange,
- HadMultipleCandidates,
- ConstructorInitRequiresZeroInit));
+ CurInit = S.Owned(
+ new (S.Context) CXXTemporaryObjectExpr(S.Context, Constructor,
+ TSInfo, ConstructorArgs,
+ ParenRange, IsListInitialization,
+ HadMultipleCandidates,
+ ConstructorInitRequiresZeroInit));
} else {
CXXConstructExpr::ConstructionKind ConstructKind =
CXXConstructExpr::CK_Complete;
@@ -4704,6 +4807,7 @@ PerformConstructorInitialization(Sema &S,
Constructor, /*Elidable=*/true,
ConstructorArgs,
HadMultipleCandidates,
+ IsListInitialization,
ConstructorInitRequiresZeroInit,
ConstructKind,
parenRange);
@@ -4712,6 +4816,7 @@ PerformConstructorInitialization(Sema &S,
Constructor,
ConstructorArgs,
HadMultipleCandidates,
+ IsListInitialization,
ConstructorInitRequiresZeroInit,
ConstructKind,
parenRange);
@@ -4802,9 +4907,9 @@ InitializationSequence::Perform(Sema &S,
if (DeclaratorDecl *DD = Entity.getDecl()) {
if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
TypeLoc TL = TInfo->getTypeLoc();
- if (IncompleteArrayTypeLoc *ArrayLoc
- = dyn_cast<IncompleteArrayTypeLoc>(&TL))
- Brackets = ArrayLoc->getBracketsRange();
+ if (IncompleteArrayTypeLoc ArrayLoc =
+ TL.getAs<IncompleteArrayTypeLoc>())
+ Brackets = ArrayLoc.getBracketsRange();
}
}
@@ -4835,7 +4940,7 @@ InitializationSequence::Perform(Sema &S,
if (Steps.empty())
return S.Owned((Expr *)0);
- if (S.getLangOpts().CPlusPlus0x && Entity.getType()->isReferenceType() &&
+ if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() &&
Args.size() == 1 && isa<InitListExpr>(Args[0]) &&
Entity.getKind() != InitializedEntity::EK_Parameter) {
// Produce a C++98 compatibility warning if we are initializing a reference
@@ -4895,7 +5000,9 @@ InitializationSequence::Perform(Sema &S,
case SK_PassByIndirectCopyRestore:
case SK_PassByIndirectRestore:
case SK_ProduceObjCObject:
- case SK_StdInitializerList: {
+ case SK_StdInitializerList:
+ case SK_OCLSamplerInit:
+ case SK_OCLZeroEvent: {
assert(Args.size() == 1);
CurInit = Args[0];
if (!CurInit.get()) return ExprError();
@@ -5047,6 +5154,7 @@ InitializationSequence::Perform(Sema &S,
CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
ConstructorArgs,
HadMultipleCandidates,
+ /*ListInit*/ false,
/*ZeroInit*/ false,
CXXConstructExpr::CK_Complete,
SourceRange());
@@ -5161,10 +5269,11 @@ InitializationSequence::Perform(Sema &S,
QualType Ty = ResultType ? ResultType->getNonReferenceType() : Step->Type;
bool IsTemporary = Entity.getType()->isReferenceType();
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty);
- InitListChecker PerformInitList(S, IsTemporary ? TempEntity : Entity,
+ InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity;
+ InitListChecker PerformInitList(S, InitEntity,
InitList, Ty, /*VerifyOnly=*/false,
Kind.getKind() != InitializationKind::IK_DirectList ||
- !S.getLangOpts().CPlusPlus0x);
+ !S.getLangOpts().CPlusPlus11);
if (PerformInitList.HadError())
return ExprError();
@@ -5180,7 +5289,9 @@ InitializationSequence::Perform(Sema &S,
InitListExpr *StructuredInitList =
PerformInitList.getFullyStructuredList();
CurInit.release();
- CurInit = S.Owned(StructuredInitList);
+ CurInit = shouldBindAsTemporary(InitEntity)
+ ? S.MaybeBindToTemporary(StructuredInitList)
+ : S.Owned(StructuredInitList);
break;
}
@@ -5202,7 +5313,8 @@ InitializationSequence::Perform(Sema &S,
CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity :
Entity,
Kind, Arg, *Step,
- ConstructorInitRequiresZeroInit);
+ ConstructorInitRequiresZeroInit,
+ /*IsListInitialization*/ true);
break;
}
@@ -5235,7 +5347,8 @@ InitializationSequence::Perform(Sema &S,
CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity
: Entity,
Kind, Args, *Step,
- ConstructorInitRequiresZeroInit);
+ ConstructorInitRequiresZeroInit,
+ /*IsListInitialization*/ false);
break;
}
@@ -5359,7 +5472,7 @@ InitializationSequence::Perform(Sema &S,
case SK_StdInitializerList: {
QualType Dest = Step->Type;
QualType E;
- bool Success = S.isStdInitializerList(Dest, &E);
+ bool Success = S.isStdInitializerList(Dest.getNonReferenceType(), &E);
(void)Success;
assert(Success && "Destination type changed?");
@@ -5390,9 +5503,9 @@ InitializationSequence::Perform(Sema &S,
for (unsigned i = 0; i < NumInits; ++i) {
Element.setElementIndex(i);
ExprResult Init = S.Owned(ILE->getInit(i));
- ExprResult Res = S.PerformCopyInitialization(Element,
- Init.get()->getExprLoc(),
- Init);
+ ExprResult Res = S.PerformCopyInitialization(
+ Element, Init.get()->getExprLoc(), Init,
+ /*TopLevelOfInitList=*/ true);
assert(!Res.isInvalid() && "Result changed since try phase.");
Converted[i] = Res.take();
}
@@ -5405,6 +5518,32 @@ InitializationSequence::Perform(Sema &S,
CurInit = S.Owned(Semantic);
break;
}
+ case SK_OCLSamplerInit: {
+ assert(Step->Type->isSamplerT() &&
+ "Sampler initialization on non sampler type.");
+
+ QualType SourceType = CurInit.get()->getType();
+ InitializedEntity::EntityKind EntityKind = Entity.getKind();
+
+ if (EntityKind == InitializedEntity::EK_Parameter) {
+ if (!SourceType->isSamplerT())
+ S.Diag(Kind.getLocation(), diag::err_sampler_argument_required)
+ << SourceType;
+ } else if (EntityKind != InitializedEntity::EK_Variable) {
+ llvm_unreachable("Invalid EntityKind!");
+ }
+
+ break;
+ }
+ case SK_OCLZeroEvent: {
+ assert(Step->Type->isEventT() &&
+ "Event initialization on non event type.");
+
+ CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
+ CK_ZeroToOCLEvent,
+ CurInit.get()->getValueKind());
+ break;
+ }
}
}
@@ -5418,9 +5557,67 @@ InitializationSequence::Perform(Sema &S,
return CurInit;
}
+/// Somewhere within T there is an uninitialized reference subobject.
+/// Dig it out and diagnose it.
+static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc,
+ QualType T) {
+ if (T->isReferenceType()) {
+ S.Diag(Loc, diag::err_reference_without_init)
+ << T.getNonReferenceType();
+ return true;
+ }
+
+ CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+ if (!RD || !RD->hasUninitializedReferenceMember())
+ return false;
+
+ for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
+ FE = RD->field_end(); FI != FE; ++FI) {
+ if (FI->isUnnamedBitfield())
+ continue;
+
+ if (DiagnoseUninitializedReference(S, FI->getLocation(), FI->getType())) {
+ S.Diag(Loc, diag::note_value_initialization_here) << RD;
+ return true;
+ }
+ }
+
+ for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
+ BE = RD->bases_end();
+ BI != BE; ++BI) {
+ if (DiagnoseUninitializedReference(S, BI->getLocStart(), BI->getType())) {
+ S.Diag(Loc, diag::note_value_initialization_here) << RD;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
//===----------------------------------------------------------------------===//
// Diagnose initialization failures
//===----------------------------------------------------------------------===//
+
+/// Emit notes associated with an initialization that failed due to a
+/// "simple" conversion failure.
+static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity,
+ Expr *op) {
+ QualType destType = entity.getType();
+ if (destType.getNonReferenceType()->isObjCObjectPointerType() &&
+ op->getType()->isObjCObjectPointerType()) {
+
+ // Emit a possible note about the conversion failing because the
+ // operand is a message send with a related result type.
+ S.EmitRelatedResultTypeNote(op);
+
+ // Emit a possible note about a return failing because we're
+ // expecting a related result type.
+ if (entity.getKind() == InitializedEntity::EK_Result)
+ S.EmitRelatedResultTypeNoteForReturn(destType);
+ }
+}
+
bool InitializationSequence::Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -5432,10 +5629,17 @@ bool InitializationSequence::Diagnose(Sema &S,
switch (Failure) {
case FK_TooManyInitsForReference:
// FIXME: Customize for the initialized entity?
- if (NumArgs == 0)
- S.Diag(Kind.getLocation(), diag::err_reference_without_init)
- << DestType.getNonReferenceType();
- else // FIXME: diagnostic below could be better!
+ if (NumArgs == 0) {
+ // Dig out the reference subobject which is uninitialized and diagnose it.
+ // If this is value-initialization, this could be nested some way within
+ // the target type.
+ assert(Kind.getKind() == InitializationKind::IK_Value ||
+ DestType->isReferenceType());
+ bool Diagnosed =
+ DiagnoseUninitializedReference(S, Kind.getLocation(), DestType);
+ assert(Diagnosed && "couldn't find uninitialized reference to diagnose");
+ (void)Diagnosed;
+ } else // FIXME: diagnostic below could be better!
S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
<< SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
break;
@@ -5558,9 +5762,7 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->isLValue()
<< Args[0]->getType()
<< Args[0]->getSourceRange();
- if (DestType.getNonReferenceType()->isObjCObjectPointerType() &&
- Args[0]->getType()->isObjCObjectPointerType())
- S.EmitRelatedResultTypeNote(Args[0]);
+ emitBadConversionNotes(S, Entity, Args[0]);
break;
case FK_ConversionFailed: {
@@ -5573,9 +5775,7 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
S.Diag(Kind.getLocation(), PDiag);
- if (DestType.getNonReferenceType()->isObjCObjectPointerType() &&
- Args[0]->getType()->isObjCObjectPointerType())
- S.EmitRelatedResultTypeNote(Args[0]);
+ emitBadConversionNotes(S, Entity, Args[0]);
break;
}
@@ -5649,7 +5849,8 @@ bool InitializationSequence::Diagnose(Sema &S,
= cast<CXXConstructorDecl>(S.CurContext);
if (Entity.getKind() == InitializedEntity::EK_Base) {
S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
- << Constructor->isImplicit()
+ << (Constructor->getInheritedConstructor() ? 2 :
+ Constructor->isImplicit() ? 1 : 0)
<< S.Context.getTypeDeclType(Constructor->getParent())
<< /*base=*/0
<< Entity.getType();
@@ -5661,7 +5862,8 @@ bool InitializationSequence::Diagnose(Sema &S,
<< S.Context.getTagDeclType(BaseDecl);
} else {
S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
- << Constructor->isImplicit()
+ << (Constructor->getInheritedConstructor() ? 2 :
+ Constructor->isImplicit() ? 1 : 0)
<< S.Context.getTypeDeclType(Constructor->getParent())
<< /*member=*/1
<< Entity.getName();
@@ -5722,7 +5924,8 @@ bool InitializationSequence::Diagnose(Sema &S,
// initialized.
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
- << Constructor->isImplicit()
+ << (Constructor->getInheritedConstructor() ? 2 :
+ Constructor->isImplicit() ? 1 : 0)
<< S.Context.getTypeDeclType(Constructor->getParent())
<< /*const=*/1
<< Entity.getName();
@@ -5746,7 +5949,7 @@ bool InitializationSequence::Diagnose(Sema &S,
InitListChecker DiagnoseInitList(S, Entity, InitList,
DestType, /*VerifyOnly=*/false,
Kind.getKind() != InitializationKind::IK_DirectList ||
- !S.getLangOpts().CPlusPlus0x);
+ !S.getLangOpts().CPlusPlus11);
assert(DiagnoseInitList.HadError() &&
"Inconsistent init list check result.");
break;
@@ -5763,7 +5966,7 @@ bool InitializationSequence::Diagnose(Sema &S,
unsigned NumInits = InitList->getNumInits();
QualType DestType = Entity.getType();
QualType E;
- bool Success = S.isStdInitializerList(DestType, &E);
+ bool Success = S.isStdInitializerList(DestType.getNonReferenceType(), &E);
(void)Success;
assert(Success && "Where did the std::initializer_list go?");
InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
@@ -6047,8 +6250,20 @@ void InitializationSequence::dump(raw_ostream &OS) const {
case SK_StdInitializerList:
OS << "std::initializer_list from initializer list";
break;
+
+ case SK_OCLSamplerInit:
+ OS << "OpenCL sampler_t from integer constant";
+ break;
+
+ case SK_OCLZeroEvent:
+ OS << "OpenCL event_t from zero";
+ break;
}
+
+ OS << " [" << S->Type.getAsString() << ']';
}
+
+ OS << '\n';
}
void InitializationSequence::dump() const {
@@ -6104,7 +6319,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
// narrowing conversion even if the value is a constant and can be
// represented exactly as an integer.
S.Diag(PostInit->getLocStart(),
- S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x?
+ S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11?
diag::warn_init_list_type_narrowing
: S.isSFINAEContext()?
diag::err_init_list_type_narrowing_sfinae
@@ -6117,7 +6332,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
case NK_Constant_Narrowing:
// A constant value was narrowed.
S.Diag(PostInit->getLocStart(),
- S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x?
+ S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11?
diag::warn_init_list_constant_narrowing
: S.isSFINAEContext()?
diag::err_init_list_constant_narrowing_sfinae
@@ -6130,7 +6345,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
case NK_Variable_Narrowing:
// A variable's value may have been narrowed.
S.Diag(PostInit->getLocStart(),
- S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x?
+ S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11?
diag::warn_init_list_variable_narrowing
: S.isSFINAEContext()?
diag::err_init_list_variable_narrowing_sfinae
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 15cd2a73e7f7..53fa6dafdd3b 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -11,13 +11,13 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/DeclSpec.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/AST/ExprCXX.h"
using namespace clang;
using namespace sema;
@@ -55,7 +55,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodType,
SourceLocation EndLoc,
- llvm::ArrayRef<ParmVarDecl *> Params) {
+ ArrayRef<ParmVarDecl *> Params) {
// C++11 [expr.prim.lambda]p5:
// The closure type for a lambda-expression has a public inline function
// call operator (13.5.4) whose parameters and return type are described by
@@ -74,7 +74,6 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
IntroducerRange.getBegin(),
MethodNameLoc),
MethodType->getType(), MethodType,
- /*isStatic=*/false,
SC_None,
/*isInline=*/true,
/*isConstExpr=*/false,
@@ -225,73 +224,153 @@ void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
}
}
-static bool checkReturnValueType(const ASTContext &Ctx, const Expr *E,
- QualType &DeducedType,
- QualType &AlternateType) {
- // Handle ReturnStmts with no expressions.
- if (!E) {
- if (AlternateType.isNull())
- AlternateType = Ctx.VoidTy;
+/// If this expression is an enumerator-like expression of some type
+/// T, return the type T; otherwise, return null.
+///
+/// Pointer comparisons on the result here should always work because
+/// it's derived from either the parent of an EnumConstantDecl
+/// (i.e. the definition) or the declaration returned by
+/// EnumType::getDecl() (i.e. the definition).
+static EnumDecl *findEnumForBlockReturn(Expr *E) {
+ // An expression is an enumerator-like expression of type T if,
+ // ignoring parens and parens-like expressions:
+ E = E->IgnoreParens();
+
+ // - it is an enumerator whose enum type is T or
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (EnumConstantDecl *D
+ = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+ return cast<EnumDecl>(D->getDeclContext());
+ }
+ return 0;
+ }
- return Ctx.hasSameType(DeducedType, Ctx.VoidTy);
+ // - it is a comma expression whose RHS is an enumerator-like
+ // expression of type T or
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Comma)
+ return findEnumForBlockReturn(BO->getRHS());
+ return 0;
}
- QualType StrictType = E->getType();
- QualType LooseType = StrictType;
-
- // In C, enum constants have the type of their underlying integer type,
- // not the enum. When inferring block return types, we should allow
- // the enum type if an enum constant is used, unless the enum is
- // anonymous (in which case there can be no variables of its type).
- if (!Ctx.getLangOpts().CPlusPlus) {
- const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
- if (DRE) {
- const Decl *D = DRE->getDecl();
- if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
- const EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext());
- if (Enum->getDeclName() || Enum->getTypedefNameForAnonDecl())
- LooseType = Ctx.getTypeDeclType(Enum);
- }
- }
+ // - it is a statement-expression whose value expression is an
+ // enumerator-like expression of type T or
+ if (StmtExpr *SE = dyn_cast<StmtExpr>(E)) {
+ if (Expr *last = dyn_cast_or_null<Expr>(SE->getSubStmt()->body_back()))
+ return findEnumForBlockReturn(last);
+ return 0;
}
- // Special case for the first return statement we find.
- // The return type has already been tentatively set, but we might still
- // have an alternate type we should prefer.
- if (AlternateType.isNull())
- AlternateType = LooseType;
-
- if (Ctx.hasSameType(DeducedType, StrictType)) {
- // FIXME: The loose type is different when there are constants from two
- // different enums. We could consider warning here.
- if (AlternateType != Ctx.DependentTy)
- if (!Ctx.hasSameType(AlternateType, LooseType))
- AlternateType = Ctx.VoidTy;
- return true;
+ // - it is a ternary conditional operator (not the GNU ?:
+ // extension) whose second and third operands are
+ // enumerator-like expressions of type T or
+ if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+ if (EnumDecl *ED = findEnumForBlockReturn(CO->getTrueExpr()))
+ if (ED == findEnumForBlockReturn(CO->getFalseExpr()))
+ return ED;
+ return 0;
}
- if (Ctx.hasSameType(DeducedType, LooseType)) {
- // Use DependentTy to signal that we're using an alternate type and may
- // need to add casts somewhere.
- AlternateType = Ctx.DependentTy;
- return true;
+ // (implicitly:)
+ // - it is an implicit integral conversion applied to an
+ // enumerator-like expression of type T or
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ // We can only see integral conversions in valid enumerator-like
+ // expressions.
+ if (ICE->getCastKind() == CK_IntegralCast)
+ return findEnumForBlockReturn(ICE->getSubExpr());
+ return 0;
}
- if (Ctx.hasSameType(AlternateType, StrictType) ||
- Ctx.hasSameType(AlternateType, LooseType)) {
- DeducedType = AlternateType;
- // Use DependentTy to signal that we're using an alternate type and may
- // need to add casts somewhere.
- AlternateType = Ctx.DependentTy;
- return true;
+ // - it is an expression of that formal enum type.
+ if (const EnumType *ET = E->getType()->getAs<EnumType>()) {
+ return ET->getDecl();
}
- return false;
+ // Otherwise, nope.
+ return 0;
+}
+
+/// Attempt to find a type T for which the returned expression of the
+/// given statement is an enumerator-like expression of that type.
+static EnumDecl *findEnumForBlockReturn(ReturnStmt *ret) {
+ if (Expr *retValue = ret->getRetValue())
+ return findEnumForBlockReturn(retValue);
+ return 0;
+}
+
+/// Attempt to find a common type T for which all of the returned
+/// expressions in a block are enumerator-like expressions of that
+/// type.
+static EnumDecl *findCommonEnumForBlockReturns(ArrayRef<ReturnStmt*> returns) {
+ ArrayRef<ReturnStmt*>::iterator i = returns.begin(), e = returns.end();
+
+ // Try to find one for the first return.
+ EnumDecl *ED = findEnumForBlockReturn(*i);
+ if (!ED) return 0;
+
+ // Check that the rest of the returns have the same enum.
+ for (++i; i != e; ++i) {
+ if (findEnumForBlockReturn(*i) != ED)
+ return 0;
+ }
+
+ // Never infer an anonymous enum type.
+ if (!ED->hasNameForLinkage()) return 0;
+
+ return ED;
+}
+
+/// Adjust the given return statements so that they formally return
+/// the given type. It should require, at most, an IntegralCast.
+static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
+ QualType returnType) {
+ for (ArrayRef<ReturnStmt*>::iterator
+ i = returns.begin(), e = returns.end(); i != e; ++i) {
+ ReturnStmt *ret = *i;
+ Expr *retValue = ret->getRetValue();
+ if (S.Context.hasSameType(retValue->getType(), returnType))
+ continue;
+
+ // Right now we only support integral fixup casts.
+ assert(returnType->isIntegralOrUnscopedEnumerationType());
+ assert(retValue->getType()->isIntegralOrUnscopedEnumerationType());
+
+ ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(retValue);
+
+ Expr *E = (cleanups ? cleanups->getSubExpr() : retValue);
+ E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast,
+ E, /*base path*/ 0, VK_RValue);
+ if (cleanups) {
+ cleanups->setSubExpr(E);
+ } else {
+ ret->setRetValue(E);
+ }
+ }
}
void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
assert(CSI.HasImplicitReturnType);
+ // C++ Core Issue #975, proposed resolution:
+ // If a lambda-expression does not include a trailing-return-type,
+ // it is as if the trailing-return-type denotes the following type:
+ // - if there are no return statements in the compound-statement,
+ // or all return statements return either an expression of type
+ // void or no expression or braced-init-list, the type void;
+ // - otherwise, if all return statements return an expression
+ // and the types of the returned expressions after
+ // lvalue-to-rvalue conversion (4.1 [conv.lval]),
+ // array-to-pointer conversion (4.2 [conv.array]), and
+ // function-to-pointer conversion (4.3 [conv.func]) are the
+ // same, that common type;
+ // - otherwise, the program is ill-formed.
+ //
+ // In addition, in blocks in non-C++ modes, if all of the return
+ // statements are enumerator-like expressions of some type T, where
+ // T has a name for linkage, then we infer the return type of the
+ // block to be that type.
+
// First case: no return statements, implicit void return type.
ASTContext &Ctx = getASTContext();
if (CSI.Returns.empty()) {
@@ -308,6 +387,17 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
if (CSI.ReturnType->isDependentType())
return;
+ // Try to apply the enum-fuzz rule.
+ if (!getLangOpts().CPlusPlus) {
+ assert(isa<BlockScopeInfo>(CSI));
+ const EnumDecl *ED = findCommonEnumForBlockReturns(CSI.Returns);
+ if (ED) {
+ CSI.ReturnType = Context.getTypeDeclType(ED);
+ adjustBlockReturnsToEnum(*this, CSI.Returns, CSI.ReturnType);
+ return;
+ }
+ }
+
// Third case: only one return statement. Don't bother doing extra work!
SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(),
E = CSI.Returns.end();
@@ -316,47 +406,25 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// General case: many return statements.
// Check that they all have compatible return types.
- // For now, that means "identical", with an exception for enum constants.
- // (In C, enum constants have the type of their underlying integer type,
- // not the type of the enum. C++ uses the type of the enum.)
- QualType AlternateType;
// We require the return types to strictly match here.
+ // Note that we've already done the required promotions as part of
+ // processing the return statement.
for (; I != E; ++I) {
const ReturnStmt *RS = *I;
const Expr *RetE = RS->getRetValue();
- if (!checkReturnValueType(Ctx, RetE, CSI.ReturnType, AlternateType)) {
- // FIXME: This is a poor diagnostic for ReturnStmts without expressions.
- Diag(RS->getLocStart(),
- diag::err_typecheck_missing_return_type_incompatible)
- << (RetE ? RetE->getType() : Ctx.VoidTy) << CSI.ReturnType
- << isa<LambdaScopeInfo>(CSI);
- // Don't bother fixing up the return statements in the block if some of
- // them are unfixable anyway.
- AlternateType = Ctx.VoidTy;
- // Continue iterating so that we keep emitting diagnostics.
- }
- }
- // If our return statements turned out to be compatible, but we needed to
- // pick a different return type, go through and fix the ones that need it.
- if (AlternateType == Ctx.DependentTy) {
- for (SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(),
- E = CSI.Returns.end();
- I != E; ++I) {
- ReturnStmt *RS = *I;
- Expr *RetE = RS->getRetValue();
- if (RetE->getType() == CSI.ReturnType)
- continue;
+ QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy);
+ if (Context.hasSameType(ReturnType, CSI.ReturnType))
+ continue;
- // Right now we only support integral fixup casts.
- assert(CSI.ReturnType->isIntegralOrUnscopedEnumerationType());
- assert(RetE->getType()->isIntegralOrUnscopedEnumerationType());
- ExprResult Casted = ImpCastExprToType(RetE, CSI.ReturnType,
- CK_IntegralCast);
- assert(Casted.isUsable());
- RS->setRetValue(Casted.take());
- }
+ // FIXME: This is a poor diagnostic for ReturnStmts without expressions.
+ // TODO: It's possible that the *first* return is the divergent one.
+ Diag(RS->getLocStart(),
+ diag::err_typecheck_missing_return_type_incompatible)
+ << ReturnType << CSI.ReturnType
+ << isa<LambdaScopeInfo>(CSI);
+ // Continue iterating so that we keep emitting diagnostics.
}
}
@@ -376,7 +444,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
bool ExplicitResultType = true;
bool ContainsUnexpandedParameterPack = false;
SourceLocation EndLoc;
- llvm::SmallVector<ParmVarDecl *, 8> Params;
+ SmallVector<ParmVarDecl *, 8> Params;
if (ParamInfo.getNumTypeObjects() == 0) {
// C++11 [expr.prim.lambda]p4:
// If a lambda-expression does not include a lambda-declarator, it is as
@@ -385,7 +453,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
EPI.HasTrailingReturn = true;
EPI.TypeQuals |= DeclSpec::TQ_const;
QualType MethodTy = Context.getFunctionType(Context.DependentTy,
- /*Args=*/0, /*NumArgs=*/0, EPI);
+ ArrayRef<QualType>(),
+ EPI);
MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
ExplicitParams = false;
ExplicitResultType = false;
@@ -449,7 +518,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// Handle explicit captures.
SourceLocation PrevCaptureLoc
= Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
- for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
+ for (SmallVector<LambdaCapture, 4>::const_iterator
C = Intro.Captures.begin(),
E = Intro.Captures.end();
C != E;
@@ -628,16 +697,18 @@ static void addFunctionPointerConversion(Sema &S,
{
FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
ExtInfo.TypeQuals = 0;
- FunctionTy = S.Context.getFunctionType(Proto->getResultType(),
- Proto->arg_type_begin(),
- Proto->getNumArgs(),
- ExtInfo);
+ FunctionTy =
+ S.Context.getFunctionType(Proto->getResultType(),
+ ArrayRef<QualType>(Proto->arg_type_begin(),
+ Proto->getNumArgs()),
+ ExtInfo);
FunctionPtrTy = S.Context.getPointerType(FunctionTy);
}
FunctionProtoType::ExtProtoInfo ExtInfo;
ExtInfo.TypeQuals = Qualifiers::Const;
- QualType ConvTy = S.Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo);
+ QualType ConvTy =
+ S.Context.getFunctionType(FunctionPtrTy, ArrayRef<QualType>(), ExtInfo);
SourceLocation Loc = IntroducerRange.getBegin();
DeclarationName Name
@@ -666,7 +737,7 @@ static void addFunctionPointerConversion(Sema &S,
= CXXMethodDecl::Create(S.Context, Class, Loc,
DeclarationNameInfo(Name, Loc), FunctionTy,
CallOperator->getTypeSourceInfo(),
- /*IsStatic=*/true, SC_Static, /*IsInline=*/true,
+ SC_Static, /*IsInline=*/true,
/*IsConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
SmallVector<ParmVarDecl *, 4> InvokeParams;
@@ -679,7 +750,6 @@ static void addFunctionPointerConversion(Sema &S,
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
- From->getStorageClassAsWritten(),
/*DefaultArg=*/0));
}
Invoke->setParams(InvokeParams);
@@ -701,15 +771,16 @@ static void addBlockPointerConversion(Sema &S,
ExtInfo.TypeQuals = 0;
QualType FunctionTy
= S.Context.getFunctionType(Proto->getResultType(),
- Proto->arg_type_begin(),
- Proto->getNumArgs(),
+ ArrayRef<QualType>(Proto->arg_type_begin(),
+ Proto->getNumArgs()),
ExtInfo);
BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
}
FunctionProtoType::ExtProtoInfo ExtInfo;
ExtInfo.TypeQuals = Qualifiers::Const;
- QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, 0, 0, ExtInfo);
+ QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, ArrayRef<QualType>(),
+ ExtInfo);
SourceLocation Loc = IntroducerRange.getBegin();
DeclarationName Name
@@ -734,8 +805,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope,
bool IsInstantiation) {
// Collect information from the lambda scope.
- llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
- llvm::SmallVector<Expr *, 4> CaptureInits;
+ SmallVector<LambdaExpr::Capture, 4> Captures;
+ SmallVector<Expr *, 4> CaptureInits;
LambdaCaptureDefault CaptureDefault;
CXXRecordDecl *Class;
CXXMethodDecl *CallOperator;
@@ -744,8 +815,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
bool ExplicitResultType;
bool LambdaExprNeedsCleanups;
bool ContainsUnexpandedParameterPack;
- llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
- llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
+ SmallVector<VarDecl *, 4> ArrayIndexVars;
+ SmallVector<unsigned, 4> ArrayIndexStarts;
{
LambdaScopeInfo *LSI = getCurLambda();
CallOperator = LSI->CallOperator;
@@ -821,8 +892,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
= CallOperator->getType()->getAs<FunctionProtoType>();
QualType FunctionTy
= Context.getFunctionType(LSI->ReturnType,
- Proto->arg_type_begin(),
- Proto->getNumArgs(),
+ ArrayRef<QualType>(Proto->arg_type_begin(),
+ Proto->getNumArgs()),
Proto->getExtProtoInfo());
CallOperator->setType(FunctionTy);
}
@@ -902,8 +973,8 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
CXXRecordDecl *Lambda = Conv->getParent();
CXXMethodDecl *CallOperator
= cast<CXXMethodDecl>(
- *Lambda->lookup(
- Context.DeclarationNames.getCXXOperatorName(OO_Call)).first);
+ Lambda->lookup(
+ Context.DeclarationNames.getCXXOperatorName(OO_Call)).front());
CallOperator->setReferenced();
CallOperator->setUsed();
@@ -937,7 +1008,6 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
- From->getStorageClassAsWritten(),
/*DefaultArg=*/0));
}
Block->setParams(BlockParams);
@@ -952,7 +1022,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation,
ConvLocation, 0,
Src->getType(), CapVarTSI,
- SC_None, SC_None);
+ SC_None);
BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false,
/*Nested=*/false, /*Copy=*/Init.take());
Block->setCaptures(Context, &Capture, &Capture + 1,
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index f6987e7bfbe0..f26b8ed7f7ae 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -11,16 +11,7 @@
// Objective-C++.
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Overload.h"
-#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/TemplateDeduction.h"
-#include "clang/Sema/ExternalSemaSource.h"
-#include "clang/Sema/TypoCorrection.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
@@ -32,8 +23,17 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
-#include "llvm/ADT/SetVector.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Overload.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/TypoCorrection.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/TinyPtrVector.h"
@@ -287,10 +287,10 @@ void LookupResult::configure() {
IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus,
isForRedeclaration());
- // If we're looking for one of the allocation or deallocation
- // operators, make sure that the implicitly-declared new and delete
- // operators can be found.
if (!isForRedeclaration()) {
+ // If we're looking for one of the allocation or deallocation
+ // operators, make sure that the implicitly-declared new and delete
+ // operators can be found.
switch (NameInfo.getName().getCXXOverloadedOperator()) {
case OO_New:
case OO_Delete:
@@ -302,6 +302,15 @@ void LookupResult::configure() {
default:
break;
}
+
+ // Compiler builtins are always visible, regardless of where they end
+ // up being declared.
+ if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) {
+ if (unsigned BuiltinID = Id->getBuiltinID()) {
+ if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ AllowHidden = true;
+ }
+ }
}
}
@@ -371,6 +380,12 @@ void LookupResult::resolveKind() {
NamedDecl *D = Decls[I]->getUnderlyingDecl();
D = cast<NamedDecl>(D->getCanonicalDecl());
+ // Ignore an invalid declaration unless it's the only one left.
+ if (D->isInvalidDecl() && I < N-1) {
+ Decls[I] = Decls[--N];
+ continue;
+ }
+
// 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
@@ -451,9 +466,9 @@ void LookupResult::resolveKind() {
void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
CXXBasePaths::const_paths_iterator I, E;
- DeclContext::lookup_iterator DI, DE;
for (I = P.begin(), E = P.end(); I != E; ++I)
- for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI)
+ for (DeclContext::lookup_iterator DI = I->Decls.begin(),
+ DE = I->Decls.end(); DI != DE; ++DI)
addDecl(*DI);
}
@@ -528,22 +543,17 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
/// \brief Determine whether we can declare a special member function within
/// the class at this point.
-static bool CanDeclareSpecialMemberFunction(ASTContext &Context,
- const CXXRecordDecl *Class) {
+static bool CanDeclareSpecialMemberFunction(const CXXRecordDecl *Class) {
// We need to have a definition for the class.
if (!Class->getDefinition() || Class->isDependentContext())
return false;
// We can't be in the middle of defining the class.
- if (const RecordType *RecordTy
- = Context.getTypeDeclType(Class)->getAs<RecordType>())
- return !RecordTy->isBeingDefined();
-
- return false;
+ return !Class->isBeingDefined();
}
void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
- if (!CanDeclareSpecialMemberFunction(Context, Class))
+ if (!CanDeclareSpecialMemberFunction(Class))
return;
// If the default constructor has not yet been declared, do so now.
@@ -551,14 +561,14 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
DeclareImplicitDefaultConstructor(Class);
// If the copy constructor has not yet been declared, do so now.
- if (!Class->hasDeclaredCopyConstructor())
+ if (Class->needsImplicitCopyConstructor())
DeclareImplicitCopyConstructor(Class);
// If the copy assignment operator has not yet been declared, do so now.
- if (!Class->hasDeclaredCopyAssignment())
+ if (Class->needsImplicitCopyAssignment())
DeclareImplicitCopyAssignment(Class);
- if (getLangOpts().CPlusPlus0x) {
+ if (getLangOpts().CPlusPlus11) {
// If the move constructor has not yet been declared, do so now.
if (Class->needsImplicitMoveConstructor())
DeclareImplicitMoveConstructor(Class); // might not actually do it
@@ -569,7 +579,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
}
// If the destructor has not yet been declared, do so now.
- if (!Class->hasDeclaredDestructor())
+ if (Class->needsImplicitDestructor())
DeclareImplicitDestructor(Class);
}
@@ -602,14 +612,13 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S,
switch (Name.getNameKind()) {
case DeclarationName::CXXConstructorName:
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
- if (Record->getDefinition() &&
- CanDeclareSpecialMemberFunction(S.Context, Record)) {
+ if (Record->getDefinition() && CanDeclareSpecialMemberFunction(Record)) {
CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(Record);
if (Record->needsImplicitDefaultConstructor())
S.DeclareImplicitDefaultConstructor(Class);
- if (!Record->hasDeclaredCopyConstructor())
+ if (Record->needsImplicitCopyConstructor())
S.DeclareImplicitCopyConstructor(Class);
- if (S.getLangOpts().CPlusPlus0x &&
+ if (S.getLangOpts().CPlusPlus11 &&
Record->needsImplicitMoveConstructor())
S.DeclareImplicitMoveConstructor(Class);
}
@@ -617,8 +626,8 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S,
case DeclarationName::CXXDestructorName:
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
- if (Record->getDefinition() && !Record->hasDeclaredDestructor() &&
- CanDeclareSpecialMemberFunction(S.Context, Record))
+ if (Record->getDefinition() && Record->needsImplicitDestructor() &&
+ CanDeclareSpecialMemberFunction(Record))
S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record));
break;
@@ -627,12 +636,11 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S,
break;
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) {
- if (Record->getDefinition() &&
- CanDeclareSpecialMemberFunction(S.Context, Record)) {
+ if (Record->getDefinition() && CanDeclareSpecialMemberFunction(Record)) {
CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(Record);
- if (!Record->hasDeclaredCopyAssignment())
+ if (Record->needsImplicitCopyAssignment())
S.DeclareImplicitCopyAssignment(Class);
- if (S.getLangOpts().CPlusPlus0x &&
+ if (S.getLangOpts().CPlusPlus11 &&
Record->needsImplicitMoveAssignment())
S.DeclareImplicitMoveAssignment(Class);
}
@@ -654,8 +662,9 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC);
// Perform lookup into this declaration context.
- DeclContext::lookup_const_iterator I, E;
- for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
+ DeclContext::lookup_const_result DR = DC->lookup(R.getLookupName());
+ for (DeclContext::lookup_const_iterator I = DR.begin(), E = DR.end(); I != E;
+ ++I) {
NamedDecl *D = *I;
if ((D = R.getAcceptableDecl(D))) {
R.addDecl(D);
@@ -680,9 +689,8 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
if (!Record->isCompleteDefinition())
return Found;
- const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
- for (UnresolvedSetImpl::iterator U = Unresolved->begin(),
- UEnd = Unresolved->end(); U != UEnd; ++U) {
+ for (CXXRecordDecl::conversion_iterator U = Record->conversion_begin(),
+ UEnd = Record->conversion_end(); U != UEnd; ++U) {
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
if (!ConvTemplate)
continue;
@@ -723,7 +731,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
EPI.NumExceptions = 0;
QualType ExpectedType
= R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(),
- 0, 0, EPI);
+ ArrayRef<QualType>(), EPI);
// Perform template argument deduction against the type that we would
// expect the function to have.
@@ -946,6 +954,21 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
continue;
}
+ // If this is a file context, we need to perform unqualified name
+ // lookup considering using directives.
+ if (Ctx->isFileContext()) {
+ UnqualUsingDirectiveSet UDirs;
+ UDirs.visit(Ctx, Ctx);
+ UDirs.done();
+
+ if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) {
+ R.resolveKind();
+ return true;
+ }
+
+ continue;
+ }
+
// Perform qualified name lookup into this context.
// FIXME: In some cases, we know that every name that could be found by
// this qualified name lookup will also be on the identifier chain. For
@@ -980,7 +1003,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// Unqualified name lookup in C++ requires looking into scopes
// that aren't strictly lexical, and therefore we walk through the
// context as well as walking through the scopes.
-
for (; S; S = S->getParent()) {
// Check whether the IdResolver has anything in this scope.
bool Found = false;
@@ -1344,7 +1366,7 @@ static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
Path.Decls = BaseRecord->lookup(N);
- return Path.Decls.first != Path.Decls.second;
+ return !Path.Decls.empty();
}
/// \brief Determine whether the given set of member declarations contains only
@@ -1530,13 +1552,13 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// We found members of the given name in two subobjects of
// different types. If the declaration sets aren't the same, this
// this lookup is ambiguous.
- if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second)) {
+ if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) {
CXXBasePaths::paths_iterator FirstPath = Paths.begin();
- DeclContext::lookup_iterator FirstD = FirstPath->Decls.first;
- DeclContext::lookup_iterator CurrentD = Path->Decls.first;
+ DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin();
+ DeclContext::lookup_iterator CurrentD = Path->Decls.begin();
- while (FirstD != FirstPath->Decls.second &&
- CurrentD != Path->Decls.second) {
+ while (FirstD != FirstPath->Decls.end() &&
+ CurrentD != Path->Decls.end()) {
if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() !=
(*CurrentD)->getUnderlyingDecl()->getCanonicalDecl())
break;
@@ -1545,8 +1567,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
++CurrentD;
}
- if (FirstD == FirstPath->Decls.second &&
- CurrentD == Path->Decls.second)
+ if (FirstD == FirstPath->Decls.end() &&
+ CurrentD == Path->Decls.end())
continue;
}
@@ -1561,7 +1583,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// A static member, a nested type or an enumerator defined in
// a base class T can unambiguously be found even if an object
// has more than one base class subobject of type T.
- if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second))
+ if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end()))
continue;
// We have found a nonstatic member name in multiple, distinct
@@ -1573,8 +1595,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// Lookup in a base class succeeded; return these results.
- DeclContext::lookup_iterator I, E;
- for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I) {
+ DeclContext::lookup_result DR = Paths.front().Decls;
+ for (DeclContext::lookup_iterator I = DR.begin(), E = DR.end(); I != E; ++I) {
NamedDecl *D = *I;
AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
D->getAccess());
@@ -1655,7 +1677,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
<< Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
<< LookupRange;
- DeclContext::lookup_iterator Found = Paths->front().Decls.first;
+ DeclContext::lookup_iterator Found = Paths->front().Decls.begin();
while (isa<CXXMethodDecl>(*Found) &&
cast<CXXMethodDecl>(*Found)->isStatic())
++Found;
@@ -1674,7 +1696,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
for (CXXBasePaths::paths_iterator Path = Paths->begin(),
PathEnd = Paths->end();
Path != PathEnd; ++Path) {
- Decl *D = *Path->Decls.first;
+ Decl *D = Path->Decls.front();
if (DeclsPrinted.insert(D).second)
Diag(D->getLocation(), diag::note_ambiguous_member_found);
}
@@ -2233,9 +2255,9 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
bool RValueThis,
bool ConstThis,
bool VolatileThis) {
- RD = RD->getDefinition();
- assert((RD && !RD->isBeingDefined()) &&
+ assert(CanDeclareSpecialMemberFunction(RD) &&
"doing special member lookup into record that isn't fully complete");
+ RD = RD->getDefinition();
if (RValueThis || ConstThis || VolatileThis)
assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) &&
"constructors and destructors always have unqualified lvalue this");
@@ -2265,7 +2287,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
SpecialMemberCache.InsertNode(Result, InsertPoint);
if (SM == CXXDestructor) {
- if (!RD->hasDeclaredDestructor())
+ if (RD->needsImplicitDestructor())
DeclareImplicitDestructor(RD);
CXXDestructorDecl *DD = RD->getDestructor();
assert(DD && "record without a destructor");
@@ -2294,15 +2316,15 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
} else {
if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) {
Name = Context.DeclarationNames.getCXXConstructorName(CanTy);
- if (!RD->hasDeclaredCopyConstructor())
+ if (RD->needsImplicitCopyConstructor())
DeclareImplicitCopyConstructor(RD);
- if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveConstructor())
+ if (getLangOpts().CPlusPlus11 && RD->needsImplicitMoveConstructor())
DeclareImplicitMoveConstructor(RD);
} else {
Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
- if (!RD->hasDeclaredCopyAssignment())
+ if (RD->needsImplicitCopyAssignment())
DeclareImplicitCopyAssignment(RD);
- if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveAssignment())
+ if (getLangOpts().CPlusPlus11 && RD->needsImplicitMoveAssignment())
DeclareImplicitMoveAssignment(RD);
}
@@ -2345,12 +2367,11 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
// resolution. Lookup is only performed directly into the class since there
// will always be a (possibly implicit) declaration to shadow any others.
OverloadCandidateSet OCS((SourceLocation()));
- DeclContext::lookup_iterator I, E;
+ DeclContext::lookup_result R = RD->lookup(Name);
- llvm::tie(I, E) = RD->lookup(Name);
- assert((I != E) &&
+ assert(!R.empty() &&
"lookup for a constructor or assignment operator was empty");
- for ( ; I != E; ++I) {
+ for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
Decl *Cand = *I;
if (Cand->isInvalidDecl())
@@ -2451,12 +2472,12 @@ CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class,
/// \brief Look up the constructors for the given class.
DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
// If the implicit constructors have not yet been declared, do so now.
- if (CanDeclareSpecialMemberFunction(Context, Class)) {
+ if (CanDeclareSpecialMemberFunction(Class)) {
if (Class->needsImplicitDefaultConstructor())
DeclareImplicitDefaultConstructor(Class);
- if (!Class->hasDeclaredCopyConstructor())
+ if (Class->needsImplicitCopyConstructor())
DeclareImplicitCopyConstructor(Class);
- if (getLangOpts().CPlusPlus0x && Class->needsImplicitMoveConstructor())
+ if (getLangOpts().CPlusPlus11 && Class->needsImplicitMoveConstructor())
DeclareImplicitMoveConstructor(Class);
}
@@ -2544,7 +2565,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
if (FD->getNumParams() == 1 &&
FD->getParamDecl(0)->getType()->getAs<PointerType>())
IsRaw = true;
- else {
+ else if (FD->getNumParams() == ArgTys.size()) {
IsExactMatch = true;
for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) {
QualType ParamTy = FD->getParamDecl(ArgIdx)->getType();
@@ -2690,8 +2711,9 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
// associated classes are visible within their respective
// namespaces even if they are not visible during an ordinary
// lookup (11.4).
- DeclContext::lookup_iterator I, E;
- for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
+ DeclContext::lookup_result R = (*NS)->lookup(Name);
+ for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
+ ++I) {
NamedDecl *D = *I;
// If the only declaration here is an ordinary friend, consider
// it only if it was declared in an associated classes.
@@ -2850,8 +2872,10 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
for (DeclContext::all_lookups_iterator L = Ctx->lookups_begin(),
LEnd = Ctx->lookups_end();
L != LEnd; ++L) {
- for (DeclContext::lookup_result R = *L; R.first != R.second; ++R.first) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*R.first)) {
+ DeclContext::lookup_result R = *L;
+ for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
+ ++I) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*I)) {
if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
Visited.add(ND);
@@ -2918,10 +2942,12 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Traverse the contexts of Objective-C classes.
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) {
// Traverse categories.
- for (ObjCCategoryDecl *Category = IFace->getCategoryList();
- Category; Category = Category->getNextClassCategory()) {
+ for (ObjCInterfaceDecl::visible_categories_iterator
+ Cat = IFace->visible_categories_begin(),
+ CatEnd = IFace->visible_categories_end();
+ Cat != CatEnd; ++Cat) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(Category, Result, QualifiedNameLookup, false,
+ LookupVisibleDecls(*Cat, Result, QualifiedNameLookup, false,
Consumer, Visited);
}
@@ -3135,7 +3161,7 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
namespace {
-typedef llvm::SmallVector<TypoCorrection, 1> TypoResultList;
+typedef SmallVector<TypoCorrection, 1> TypoResultList;
typedef llvm::StringMap<TypoResultList, llvm::BumpPtrAllocator> TypoResultsMap;
typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
@@ -3560,7 +3586,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
Consumer.addKeywordResult("typename");
Consumer.addKeywordResult("wchar_t");
- if (SemaRef.getLangOpts().CPlusPlus0x) {
+ if (SemaRef.getLangOpts().CPlusPlus11) {
Consumer.addKeywordResult("char16_t");
Consumer.addKeywordResult("char32_t");
Consumer.addKeywordResult("constexpr");
@@ -3599,7 +3625,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
cast<CXXMethodDecl>(SemaRef.CurContext)->isInstance())
Consumer.addKeywordResult("this");
- if (SemaRef.getLangOpts().CPlusPlus0x) {
+ if (SemaRef.getLangOpts().CPlusPlus11) {
Consumer.addKeywordResult("alignof");
Consumer.addKeywordResult("nullptr");
}
@@ -3656,7 +3682,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
if (SemaRef.getLangOpts().CPlusPlus) {
Consumer.addKeywordResult("using");
- if (SemaRef.getLangOpts().CPlusPlus0x)
+ if (SemaRef.getLangOpts().CPlusPlus11)
Consumer.addKeywordResult("static_assert");
}
}
@@ -3731,6 +3757,17 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (!ActiveTemplateInstantiations.empty())
return TypoCorrection();
+ // Don't try to correct 'super'.
+ if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier())
+ return TypoCorrection();
+
+ // This is for testing.
+ if (Diags.getWarnOnSpellCheck()) {
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
+ "spell-checking initiated for %0");
+ Diag(TypoName.getLoc(), DiagID) << TypoName.getName();
+ }
+
NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
TypoCorrectionConsumer Consumer(*this, Typo);
@@ -3860,7 +3897,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
KnownNamespaces[ExternalKnownNamespaces[I]] = true;
}
- for (llvm::DenseMap<NamespaceDecl*, bool>::iterator
+ for (llvm::MapVector<NamespaceDecl*, bool>::iterator
KNI = KnownNamespaces.begin(),
KNIEnd = KnownNamespaces.end();
KNI != KNIEnd; ++KNI)
@@ -3869,7 +3906,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Weed out any names that could not be found by name lookup or, if a
// CorrectionCandidateCallback object was provided, failed validation.
- llvm::SmallVector<TypoCorrection, 16> QualifiedResults;
+ SmallVector<TypoCorrection, 16> QualifiedResults;
LookupResult TmpRes(*this, TypoName, LookupKind);
TmpRes.suppressDiagnostics();
while (!Consumer.empty()) {
@@ -3971,9 +4008,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Only perform the qualified lookups for C++
if (SearchNamespaces) {
TmpRes.suppressDiagnostics();
- for (llvm::SmallVector<TypoCorrection,
- 16>::iterator QRI = QualifiedResults.begin(),
- QRIEnd = QualifiedResults.end();
+ for (SmallVector<TypoCorrection,
+ 16>::iterator QRI = QualifiedResults.begin(),
+ QRIEnd = QualifiedResults.end();
QRI != QRIEnd; ++QRI) {
for (NamespaceSpecifierSet::iterator NI = Namespaces.begin(),
NIEnd = Namespaces.end();
@@ -4094,7 +4131,7 @@ void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
if (isKeyword())
CorrectionDecls.clear();
- CorrectionDecls.push_back(CDecl);
+ CorrectionDecls.push_back(CDecl->getUnderlyingDecl());
if (!CorrectionName)
CorrectionName = CDecl->getDeclName();
@@ -4111,3 +4148,21 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const {
return CorrectionName.getAsString();
}
+
+bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candidate) {
+ if (!candidate.isResolved())
+ return true;
+
+ if (candidate.isKeyword())
+ return WantTypeSpecifiers || WantExpressionKeywords || WantCXXNamedCasts ||
+ WantRemainingKeywords || WantObjCSuper;
+
+ for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(),
+ CDeclEnd = candidate.end();
+ CDecl != CDeclEnd; ++CDecl) {
+ if (!isa<TypeDecl>(*CDecl))
+ return true;
+ }
+
+ return WantTypeSpecifiers;
+}
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 8d708607f6eb..c348a9cb7687 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -13,16 +13,16 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Initialization.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/ASTMutationListener.h"
-#include "clang/Lex/Lexer.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
-#include "clang/Lex/Preprocessor.h"
using namespace clang;
@@ -112,6 +112,33 @@ static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) {
return 0;
}
+/// \brief Check this Objective-C property against a property declared in the
+/// given protocol.
+static void
+CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
+ ObjCProtocolDecl *Proto,
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 16> &Known) {
+ // Have we seen this protocol before?
+ if (!Known.insert(Proto))
+ return;
+
+ // Look for a property with the same name.
+ DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName());
+ for (unsigned I = 0, N = R.size(); I != N; ++I) {
+ if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
+ S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier());
+ return;
+ }
+ }
+
+ // Check this property against any protocols we inherit.
+ for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+ PEnd = Proto->protocol_end();
+ P != PEnd; ++P) {
+ CheckPropertyAgainstProtocol(S, Prop, *P, Known);
+ }
+}
+
Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
SourceLocation LParenLoc,
FieldDeclarator &FD,
@@ -139,34 +166,31 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
!(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) &&
!(Attributes & ObjCDeclSpec::DQ_PR_weak)));
- // Proceed with constructing the ObjCPropertDecls.
+ // Proceed with constructing the ObjCPropertyDecls.
ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
- if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
+ ObjCPropertyDecl *Res = 0;
+ if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
if (CDecl->IsClassExtension()) {
- Decl *Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
+ Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
FD, GetterSel, SetterSel,
isAssign, isReadWrite,
Attributes,
ODS.getPropertyAttributes(),
isOverridingProperty, TSI,
MethodImplKind);
- if (Res) {
- CheckObjCPropertyAttributes(Res, AtLoc, Attributes, false);
- if (getLangOpts().ObjCAutoRefCount)
- checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res));
- }
- ActOnDocumentableDecl(Res);
- return Res;
+ if (!Res)
+ return 0;
}
-
- ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
- GetterSel, SetterSel,
- isAssign, isReadWrite,
- Attributes,
- ODS.getPropertyAttributes(),
- TSI, MethodImplKind);
- if (lexicalDC)
- Res->setLexicalDeclContext(lexicalDC);
+ }
+
+ if (!Res) {
+ Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
+ GetterSel, SetterSel, isAssign, isReadWrite,
+ Attributes, ODS.getPropertyAttributes(),
+ TSI, MethodImplKind);
+ if (lexicalDC)
+ Res->setLexicalDeclContext(lexicalDC);
+ }
// Validate the attributes on the @property.
CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
@@ -176,6 +200,52 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
if (getLangOpts().ObjCAutoRefCount)
checkARCPropertyDecl(*this, Res);
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos;
+ if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+ // For a class, compare the property against a property in our superclass.
+ bool FoundInSuper = false;
+ if (ObjCInterfaceDecl *Super = IFace->getSuperClass()) {
+ DeclContext::lookup_result R = Super->lookup(Res->getDeclName());
+ for (unsigned I = 0, N = R.size(); I != N; ++I) {
+ if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
+ DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier());
+ FoundInSuper = true;
+ break;
+ }
+ }
+ }
+
+ if (FoundInSuper) {
+ // Also compare the property against a property in our protocols.
+ for (ObjCInterfaceDecl::protocol_iterator P = IFace->protocol_begin(),
+ PEnd = IFace->protocol_end();
+ P != PEnd; ++P) {
+ CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
+ }
+ } else {
+ // Slower path: look in all protocols we referenced.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = IFace->all_referenced_protocol_begin(),
+ PEnd = IFace->all_referenced_protocol_end();
+ P != PEnd; ++P) {
+ CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
+ }
+ }
+ } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
+ for (ObjCCategoryDecl::protocol_iterator P = Cat->protocol_begin(),
+ PEnd = Cat->protocol_end();
+ P != PEnd; ++P) {
+ CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
+ }
+ } else {
+ ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
+ for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+ PEnd = Proto->protocol_end();
+ P != PEnd; ++P) {
+ CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
+ }
+ }
+
ActOnDocumentableDecl(Res);
return Res;
}
@@ -251,7 +321,7 @@ static unsigned getOwnershipRule(unsigned attr) {
ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
}
-Decl *
+ObjCPropertyDecl *
Sema::HandlePropertyInClassExtension(Scope *S,
SourceLocation AtLoc,
SourceLocation LParenLoc,
@@ -270,20 +340,22 @@ Sema::HandlePropertyInClassExtension(Scope *S,
IdentifierInfo *PropertyId = FD.D.getIdentifier();
ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
- if (CCPrimary)
+ if (CCPrimary) {
// Check for duplicate declaration of this property in current and
// other class extensions.
- for (const ObjCCategoryDecl *ClsExtDecl =
- CCPrimary->getFirstClassExtension();
- ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
- if (ObjCPropertyDecl *prevDecl =
- ObjCPropertyDecl::findPropertyDecl(ClsExtDecl, PropertyId)) {
+ for (ObjCInterfaceDecl::known_extensions_iterator
+ Ext = CCPrimary->known_extensions_begin(),
+ ExtEnd = CCPrimary->known_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ if (ObjCPropertyDecl *prevDecl
+ = ObjCPropertyDecl::findPropertyDecl(*Ext, PropertyId)) {
Diag(AtLoc, diag::err_duplicate_property);
Diag(prevDecl->getLocation(), diag::note_property_declare);
return 0;
}
}
-
+ }
+
// Create a new ObjCPropertyDecl with the DeclContext being
// the class extension.
// FIXME. We should really be using CreatePropertyDecl for this.
@@ -296,6 +368,10 @@ Sema::HandlePropertyInClassExtension(Scope *S,
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);
// Set setter/getter selector name. Needed later.
PDecl->setGetterName(GetterSel);
PDecl->setSetterName(SetterSel);
@@ -577,20 +653,20 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
switch (propertyLifetime) {
case Qualifiers::OCL_Strong:
- S.Diag(propertyImplLoc, diag::err_arc_strong_property_ownership)
+ S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership)
<< property->getDeclName()
<< ivar->getDeclName()
<< ivarLifetime;
break;
case Qualifiers::OCL_Weak:
- S.Diag(propertyImplLoc, diag::error_weak_property)
+ S.Diag(ivar->getLocation(), diag::error_weak_property)
<< property->getDeclName()
<< ivar->getDeclName();
break;
case Qualifiers::OCL_ExplicitNone:
- S.Diag(propertyImplLoc, diag::err_arc_assign_property_ownership)
+ S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership)
<< property->getDeclName()
<< ivar->getDeclName()
<< ((property->getPropertyAttributesAsWritten()
@@ -606,6 +682,8 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
}
S.Diag(property->getLocation(), diag::note_property_declare);
+ if (propertyImplLoc.isValid())
+ S.Diag(propertyImplLoc, diag::note_property_synthesize);
}
/// setImpliedPropertyAttributeForReadOnlyProperty -
@@ -644,16 +722,18 @@ DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl,
ObjCPropertyDecl *property) {
unsigned Attributes = property->getPropertyAttributesAsWritten();
bool warn = (Attributes & ObjCDeclSpec::DQ_PR_readonly);
- for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension();
- CDecl; CDecl = CDecl->getNextClassExtension()) {
+ for (ObjCInterfaceDecl::known_extensions_iterator
+ Ext = ClassDecl->known_extensions_begin(),
+ ExtEnd = ClassDecl->known_extensions_end();
+ Ext != ExtEnd; ++Ext) {
ObjCPropertyDecl *ClassExtProperty = 0;
- for (ObjCContainerDecl::prop_iterator P = CDecl->prop_begin(),
- E = CDecl->prop_end(); P != E; ++P) {
- if ((*P)->getIdentifier() == property->getIdentifier()) {
- ClassExtProperty = *P;
+ DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
+ for (unsigned I = 0, N = R.size(); I != N; ++I) {
+ ClassExtProperty = dyn_cast<ObjCPropertyDecl>(R[0]);
+ if (ClassExtProperty)
break;
- }
}
+
if (ClassExtProperty) {
warn = false;
unsigned classExtPropertyAttr =
@@ -763,22 +843,40 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
return 0;
}
}
-
if (Synthesize&&
(PIkind & ObjCPropertyDecl::OBJC_PR_readonly) &&
property->hasAttr<IBOutletAttr>() &&
!AtLoc.isValid()) {
- Diag(IC->getLocation(), diag::warn_auto_readonly_iboutlet_property);
- Diag(property->getLocation(), diag::note_property_declare);
- SourceLocation readonlyLoc;
- if (LocPropertyAttribute(Context, "readonly",
- property->getLParenLoc(), readonlyLoc)) {
- SourceLocation endLoc =
- readonlyLoc.getLocWithOffset(strlen("readonly")-1);
- SourceRange ReadonlySourceRange(readonlyLoc, endLoc);
- Diag(property->getLocation(),
- diag::note_auto_readonly_iboutlet_fixup_suggest) <<
- FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
+ bool ReadWriteProperty = false;
+ // Search into the class extensions and see if 'readonly property is
+ // redeclared 'readwrite', then no warning is to be issued.
+ for (ObjCInterfaceDecl::known_extensions_iterator
+ Ext = IDecl->known_extensions_begin(),
+ ExtEnd = IDecl->known_extensions_end(); Ext != ExtEnd; ++Ext) {
+ DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
+ if (!R.empty())
+ if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) {
+ PIkind = ExtProp->getPropertyAttributesAsWritten();
+ if (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) {
+ ReadWriteProperty = true;
+ break;
+ }
+ }
+ }
+
+ if (!ReadWriteProperty) {
+ Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
+ << property->getName();
+ SourceLocation readonlyLoc;
+ if (LocPropertyAttribute(Context, "readonly",
+ property->getLParenLoc(), readonlyLoc)) {
+ SourceLocation endLoc =
+ readonlyLoc.getLocWithOffset(strlen("readonly")-1);
+ SourceRange ReadonlySourceRange(readonlyLoc, endLoc);
+ Diag(property->getLocation(),
+ diag::note_auto_readonly_iboutlet_fixup_suggest) <<
+ FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
+ }
}
}
@@ -1036,6 +1134,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
MarkDeclRefReferenced(SelfExpr);
Expr *IvarRefExpr =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
+ Ivar->getLocation(),
SelfExpr, true, true);
ExprResult Res =
PerformCopyInitialization(InitializedEntity::InitializeResult(
@@ -1071,6 +1170,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
MarkDeclRefReferenced(SelfExpr);
Expr *lhs =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
+ Ivar->getLocation(),
SelfExpr, true, true);
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
ParmVarDecl *Param = (*P);
@@ -1198,15 +1298,21 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
}
if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
- != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic))
+ != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
Diag(Property->getLocation(), diag::warn_property_attribute)
<< Property->getDeclName() << "atomic" << inheritedName;
- if (Property->getSetterName() != SuperProperty->getSetterName())
+ Diag(SuperProperty->getLocation(), diag::note_property_declare);
+ }
+ if (Property->getSetterName() != SuperProperty->getSetterName()) {
Diag(Property->getLocation(), diag::warn_property_attribute)
<< Property->getDeclName() << "setter" << inheritedName;
- if (Property->getGetterName() != SuperProperty->getGetterName())
+ Diag(SuperProperty->getLocation(), diag::note_property_declare);
+ }
+ if (Property->getGetterName() != SuperProperty->getGetterName()) {
Diag(Property->getLocation(), diag::warn_property_attribute)
<< Property->getDeclName() << "getter" << inheritedName;
+ Diag(SuperProperty->getLocation(), diag::note_property_declare);
+ }
QualType LHSType =
Context.getCanonicalType(SuperProperty->getType());
@@ -1270,119 +1376,56 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
return false;
}
-/// ComparePropertiesInBaseAndSuper - This routine compares property
-/// declarations in base and its super class, if any, and issues
-/// diagnostics in a variety of inconsistent situations.
-///
-void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
- ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
- if (!SDecl)
- return;
- // FIXME: O(N^2)
- for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(),
- E = SDecl->prop_end(); S != E; ++S) {
- ObjCPropertyDecl *SuperPDecl = *S;
- // Does property in super class has declaration in current class?
- for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(),
- E = IDecl->prop_end(); I != E; ++I) {
- ObjCPropertyDecl *PDecl = *I;
- if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
- DiagnosePropertyMismatch(PDecl, SuperPDecl,
- SDecl->getIdentifier());
- }
- }
-}
-
/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
/// of properties declared in a protocol and compares their attribute against
/// the same property declared in the class or category.
void
-Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
- ObjCProtocolDecl *PDecl) {
- ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
- if (!IDecl) {
- // Category
- ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
+Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, ObjCProtocolDecl *PDecl) {
+ if (!CDecl)
+ return;
+
+ // Category case.
+ if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ // FIXME: We should perform this check when the property in the category
+ // is declared.
assert (CatDecl && "MatchOneProtocolPropertiesInClass");
if (!CatDecl->IsClassExtension())
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
E = PDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Pr = *P;
- ObjCCategoryDecl::prop_iterator CP, CE;
- // Is this property already in category's list of properties?
- for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP)
- if (CP->getIdentifier() == Pr->getIdentifier())
- break;
- if (CP != CE)
- // Property protocol already exist in class. Diagnose any mismatch.
- DiagnosePropertyMismatch(*CP, Pr, PDecl->getIdentifier());
+ ObjCPropertyDecl *ProtoProp = *P;
+ DeclContext::lookup_result R
+ = CatDecl->lookup(ProtoProp->getDeclName());
+ for (unsigned I = 0, N = R.size(); I != N; ++I) {
+ if (ObjCPropertyDecl *CatProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
+ if (CatProp != ProtoProp) {
+ // Property protocol already exist in class. Diagnose any mismatch.
+ DiagnosePropertyMismatch(CatProp, ProtoProp,
+ PDecl->getIdentifier());
+ }
+ }
+ }
}
return;
}
- for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
- E = PDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Pr = *P;
- ObjCInterfaceDecl::prop_iterator CP, CE;
- // Is this property already in class's list of properties?
- for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP)
- if (CP->getIdentifier() == Pr->getIdentifier())
- break;
- if (CP != CE)
- // Property protocol already exist in class. Diagnose any mismatch.
- DiagnosePropertyMismatch(*CP, Pr, PDecl->getIdentifier());
- }
-}
-/// CompareProperties - This routine compares properties
-/// declared in 'ClassOrProtocol' objects (which can be a class or an
-/// inherited protocol with the list of properties for class/category 'CDecl'
-///
-void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) {
- Decl *ClassDecl = ClassOrProtocol;
- ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
-
- if (!IDecl) {
- // Category
- ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
- assert (CatDecl && "CompareProperties");
- if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
- for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
- E = MDecl->protocol_end(); P != E; ++P)
- // Match properties of category with those of protocol (*P)
- MatchOneProtocolPropertiesInClass(CatDecl, *P);
-
- // Go thru the list of protocols for this category and recursively match
- // their properties with those in the category.
- for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
- E = CatDecl->protocol_end(); P != E; ++P)
- CompareProperties(CatDecl, *P);
- } else {
- ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
- for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
- E = MD->protocol_end(); P != E; ++P)
- MatchOneProtocolPropertiesInClass(CatDecl, *P);
+ // Class
+ // FIXME: We should perform this check when the property in the class
+ // is declared.
+ ObjCInterfaceDecl *IDecl = cast<ObjCInterfaceDecl>(CDecl);
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *ProtoProp = *P;
+ DeclContext::lookup_result R
+ = IDecl->lookup(ProtoProp->getDeclName());
+ for (unsigned I = 0, N = R.size(); I != N; ++I) {
+ if (ObjCPropertyDecl *ClassProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
+ if (ClassProp != ProtoProp) {
+ // Property protocol already exist in class. Diagnose any mismatch.
+ DiagnosePropertyMismatch(ClassProp, ProtoProp,
+ PDecl->getIdentifier());
+ }
+ }
}
- return;
- }
-
- if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
- for (ObjCInterfaceDecl::all_protocol_iterator
- P = MDecl->all_referenced_protocol_begin(),
- E = MDecl->all_referenced_protocol_end(); P != E; ++P)
- // Match properties of class IDecl with those of protocol (*P).
- MatchOneProtocolPropertiesInClass(IDecl, *P);
-
- // Go thru the list of protocols for this class and recursively match
- // their properties with those declared in the class.
- for (ObjCInterfaceDecl::all_protocol_iterator
- P = IDecl->all_referenced_protocol_begin(),
- E = IDecl->all_referenced_protocol_end(); P != E; ++P)
- CompareProperties(IDecl, *P);
- } else {
- ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
- for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
- E = MD->protocol_end(); P != E; ++P)
- MatchOneProtocolPropertiesInClass(IDecl, *P);
}
}
@@ -1402,14 +1445,14 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
// Main class has the property as 'readonly'. Must search
// through the category list to see if the property's
// attribute has been over-ridden to 'readwrite'.
- for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
- Category; Category = Category->getNextClassCategory()) {
- // Even if property is ready only, if a category has a user defined setter,
- // it is not considered read only.
- if (Category->getInstanceMethod(PDecl->getSetterName()))
+ for (ObjCInterfaceDecl::visible_categories_iterator
+ Cat = IDecl->visible_categories_begin(),
+ CatEnd = IDecl->visible_categories_end();
+ Cat != CatEnd; ++Cat) {
+ if (Cat->getInstanceMethod(PDecl->getSetterName()))
return false;
ObjCPropertyDecl *P =
- Category->FindPropertyDeclaration(PDecl->getIdentifier());
+ Cat->FindPropertyDeclaration(PDecl->getIdentifier());
if (P && !P->isReadOnly())
return false;
}
@@ -1438,7 +1481,7 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
}
/// CollectImmediateProperties - This routine collects all properties in
-/// the class and its conforming protocols; but not those it its super class.
+/// the class and its conforming protocols; but not those in its super class.
void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
ObjCContainerDecl::PropertyMap &PropMap,
ObjCContainerDecl::PropertyMap &SuperPropMap) {
@@ -1493,36 +1536,84 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
ObjCInterfaceDecl::PropertyMap &PropMap) {
if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
+ ObjCInterfaceDecl::PropertyDeclOrder PO;
while (SDecl) {
- SDecl->collectPropertiesToImplement(PropMap);
+ SDecl->collectPropertiesToImplement(PropMap, PO);
SDecl = SDecl->getSuperClass();
}
}
}
+/// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
+/// an ivar synthesized for 'Method' and 'Method' is a property accessor
+/// declared in class 'IFace'.
+bool
+Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
+ ObjCMethodDecl *Method, ObjCIvarDecl *IV) {
+ if (!IV->getSynthesize())
+ return false;
+ ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(),
+ Method->isInstanceMethod());
+ if (!IMD || !IMD->isPropertyAccessor())
+ return false;
+
+ // look up a property declaration whose one of its accessors is implemented
+ // by this method.
+ for (ObjCContainerDecl::prop_iterator P = IFace->prop_begin(),
+ E = IFace->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *property = *P;
+ if ((property->getGetterName() == IMD->getSelector() ||
+ property->getSetterName() == IMD->getSelector()) &&
+ (property->getPropertyIvarDecl() == IV))
+ return true;
+ }
+ return false;
+}
+
+
/// \brief Default synthesizes all properties which must be synthesized
/// in class's \@implementation.
void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
ObjCInterfaceDecl *IDecl) {
ObjCInterfaceDecl::PropertyMap PropMap;
- IDecl->collectPropertiesToImplement(PropMap);
+ ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder;
+ IDecl->collectPropertiesToImplement(PropMap, PropertyOrder);
if (PropMap.empty())
return;
ObjCInterfaceDecl::PropertyMap SuperPropMap;
CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
- for (ObjCInterfaceDecl::PropertyMap::iterator
- P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = P->second;
+ for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) {
+ ObjCPropertyDecl *Prop = PropertyOrder[i];
// If property to be implemented in the super class, ignore.
- if (SuperPropMap[Prop->getIdentifier()])
+ if (SuperPropMap[Prop->getIdentifier()]) {
+ ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()];
+ if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) &&
+ (PropInSuperClass->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_readonly) &&
+ !IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
+ !IDecl->HasUserDeclaredSetterMethod(Prop)) {
+ Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
+ << Prop->getIdentifier()->getName();
+ Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
+ }
continue;
+ }
// Is there a matching property synthesize/dynamic?
if (Prop->isInvalidDecl() ||
- Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
- IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier()))
+ Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional)
continue;
+ if (ObjCPropertyImplDecl *PID =
+ IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
+ if (PID->getPropertyDecl() != Prop) {
+ Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
+ << Prop->getIdentifier()->getName();
+ if (!PID->getLocation().isInvalid())
+ Diag(PID->getLocation(), diag::note_property_synthesize);
+ }
+ continue;
+ }
// Property may have been synthesized by user.
if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
continue;
@@ -1571,12 +1662,25 @@ void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) {
void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
ObjCContainerDecl *CDecl,
const SelectorSet &InsMap) {
- ObjCContainerDecl::PropertyMap SuperPropMap;
- if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
- CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
+ ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
+ ObjCInterfaceDecl *IDecl;
+ // Gather properties which need not be implemented in this class
+ // or category.
+ if (!(IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)))
+ if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ // For categories, no need to implement properties declared in
+ // its primary class (and its super classes) if property is
+ // declared in one of those containers.
+ if ((IDecl = C->getClassInterface())) {
+ ObjCInterfaceDecl::PropertyDeclOrder PO;
+ IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO);
+ }
+ }
+ if (IDecl)
+ CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
ObjCContainerDecl::PropertyMap PropMap;
- CollectImmediateProperties(CDecl, PropMap, SuperPropMap);
+ CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap);
if (PropMap.empty())
return;
@@ -1592,7 +1696,8 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
// Is there a matching propery synthesize/dynamic?
if (Prop->isInvalidDecl() ||
Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
- PropImplMap.count(Prop) || Prop->hasAttr<UnavailableAttr>())
+ PropImplMap.count(Prop) ||
+ Prop->getAvailability() == AR_Unavailable)
continue;
if (!InsMap.count(Prop->getGetterName())) {
Diag(IMPDecl->getLocation(),
@@ -1829,6 +1934,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
if (property->hasAttr<NSReturnsNotRetainedAttr>())
GetterMethod->addAttr(
::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
+
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckARCMethodDecl(GetterMethod);
} else
// A user declared getter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
@@ -1866,7 +1974,6 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
property->getType().getUnqualifiedType(),
/*TInfo=*/0,
SC_None,
- SC_None,
0);
SetterMethod->setMethodParams(Context, Argument,
ArrayRef<SourceLocation>());
@@ -1878,6 +1985,11 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// and the real context should be the same.
if (lexicalDC)
SetterMethod->setLexicalDeclContext(lexicalDC);
+
+ // It's possible for the user to have set a very odd custom
+ // setter selector that causes it to have a method family.
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckARCMethodDecl(SetterMethod);
} else
// A user declared setter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
new file mode 100644
index 000000000000..b8acb2d7310e
--- /dev/null
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -0,0 +1,181 @@
+//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file implements semantic analysis for OpenMP directives and
+/// clauses
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclOpenMP.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+using namespace clang;
+
+namespace {
+
+ class VarDeclFilterCCC : public CorrectionCandidateCallback {
+ private:
+ Sema &Actions;
+ public:
+ VarDeclFilterCCC(Sema &S) : Actions(S) { }
+ virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
+ NamedDecl *ND = Candidate.getCorrectionDecl();
+ if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
+ return VD->hasGlobalStorage() &&
+ Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
+ Actions.getCurScope());
+ }
+ return false;
+ }
+ };
+}
+Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
+ SourceLocation Loc,
+ Scope *CurScope,
+ ArrayRef<DeclarationNameInfo> IdList) {
+ SmallVector<DeclRefExpr *, 5> Vars;
+ for (ArrayRef<DeclarationNameInfo>::iterator I = IdList.begin(),
+ E = IdList.end();
+ I != E; ++I) {
+ LookupResult Lookup(*this, *I, LookupOrdinaryName);
+ LookupParsedName(Lookup, CurScope, NULL, true);
+
+ if (Lookup.isAmbiguous())
+ continue;
+
+ VarDecl *VD;
+ if (!Lookup.isSingleResult()) {
+ VarDeclFilterCCC Validator(*this);
+ TypoCorrection Corrected = CorrectTypo(*I, LookupOrdinaryName, CurScope,
+ 0, Validator);
+ std::string CorrectedStr = Corrected.getAsString(getLangOpts());
+ std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
+ if (Lookup.empty()) {
+ if (Corrected.isResolved()) {
+ Diag(I->getLoc(), diag::err_undeclared_var_use_suggest)
+ << I->getName() << CorrectedQuotedStr
+ << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
+ } else {
+ Diag(I->getLoc(), diag::err_undeclared_var_use)
+ << I->getName();
+ }
+ } else {
+ Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
+ << I->getName() << Corrected.isResolved() << CorrectedQuotedStr
+ << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
+ }
+ if (!Corrected.isResolved()) continue;
+ VD = Corrected.getCorrectionDeclAs<VarDecl>();
+ } else {
+ if (!(VD = Lookup.getAsSingle<VarDecl>())) {
+ Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
+ << I->getName() << 0;
+ Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
+ continue;
+ }
+ }
+
+ // OpenMP [2.9.2, Syntax, C/C++]
+ // Variables must be file-scope, namespace-scope, or static block-scope.
+ if (!VD->hasGlobalStorage()) {
+ Diag(I->getLoc(), diag::err_omp_global_var_arg)
+ << getOpenMPDirectiveName(OMPD_threadprivate)
+ << !VD->isStaticLocal();
+ Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+ continue;
+ }
+
+ // OpenMP [2.9.2, Restrictions, C/C++, p.2]
+ // A threadprivate directive for file-scope variables must appear outside
+ // any definition or declaration.
+ // OpenMP [2.9.2, Restrictions, C/C++, p.3]
+ // A threadprivate directive for static class member variables must appear
+ // in the class definition, in the same scope in which the member
+ // variables are declared.
+ // OpenMP [2.9.2, Restrictions, C/C++, p.4]
+ // A threadprivate directive for namespace-scope variables must appear
+ // outside any definition or declaration other than the namespace
+ // definition itself.
+ // OpenMP [2.9.2, Restrictions, C/C++, p.6]
+ // A threadprivate directive for static block-scope variables must appear
+ // in the scope of the variable and not in a nested scope.
+ NamedDecl *ND = cast<NamedDecl>(VD);
+ if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
+ Diag(I->getLoc(), diag::err_omp_var_scope)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+ continue;
+ }
+
+ // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
+ // A threadprivate directive must lexically precede all references to any
+ // of the variables in its list.
+ if (VD->isUsed()) {
+ Diag(I->getLoc(), diag::err_omp_var_used)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ continue;
+ }
+
+ QualType ExprType = VD->getType().getNonReferenceType();
+ DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD,
+ ExprType,
+ VK_RValue,
+ I->getLoc()).take());
+ Vars.push_back(Var);
+ }
+ if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) {
+ CurContext->addDecl(D);
+ return DeclGroupPtrTy::make(DeclGroupRef(D));
+ }
+ return DeclGroupPtrTy();
+}
+
+OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
+ SourceLocation Loc,
+ ArrayRef<DeclRefExpr *> VarList) {
+ SmallVector<DeclRefExpr *, 5> Vars;
+ for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(),
+ E = VarList.end();
+ I != E; ++I) {
+ VarDecl *VD = cast<VarDecl>((*I)->getDecl());
+ SourceLocation ILoc = (*I)->getLocation();
+
+ // OpenMP [2.9.2, Restrictions, C/C++, p.10]
+ // A threadprivate variable must not have an incomplete type.
+ if (RequireCompleteType(ILoc, VD->getType(),
+ diag::err_omp_incomplete_type)) {
+ continue;
+ }
+
+ // OpenMP [2.9.2, Restrictions, C/C++, p.10]
+ // A threadprivate variable must not have a reference type.
+ if (VD->getType()->isReferenceType()) {
+ Diag(ILoc, diag::err_omp_ref_type_arg)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
+ Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+ continue;
+ }
+
+ // Check if threadspecified is set.
+ if (VD->isThreadSpecified()) {
+ Diag(ILoc, diag::err_omp_var_thread_local) << VD;
+ Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+ continue;
+ }
+
+ Vars.push_back(*I);
+ }
+ return Vars.empty() ?
+ 0 : OMPThreadPrivateDecl::Create(Context,
+ getCurLexicalContext(),
+ Loc, Vars);
+}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 911187857fe1..89d495ddc197 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1,4 +1,4 @@
-//===--- SemaOverload.cpp - C++ Overloading ---------------------*- C++ -*-===//
+//===--- SemaOverload.cpp - C++ Overloading -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,13 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Template.h"
-#include "clang/Sema/TemplateDeduction.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Overload.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -25,26 +19,37 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/STLExtras.h"
#include <algorithm>
namespace clang {
using namespace sema;
-/// A convenience routine for creating a decayed reference to a
-/// function.
+/// A convenience routine for creating a decayed reference to a function.
static ExprResult
-CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, bool HadMultipleCandidates,
+CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
+ bool HadMultipleCandidates,
SourceLocation Loc = SourceLocation(),
const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){
DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(),
VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
DRE->setHadMultipleCandidates(true);
+
+ S.MarkDeclRefReferenced(DRE);
+ S.DiagnoseUseOfDecl(FoundDecl, Loc);
+
ExprResult E = S.Owned(DRE);
E = S.DefaultFunctionArrayConversion(E.take());
if (E.isInvalid())
@@ -535,12 +540,16 @@ AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
namespace {
// Structure used by OverloadCandidate::DeductionFailureInfo to store
- // template parameter and template argument information.
- struct DFIParamWithArguments {
- TemplateParameter Param;
+ // template argument information.
+ struct DFIArguments {
TemplateArgument FirstArg;
TemplateArgument SecondArg;
};
+ // Structure used by OverloadCandidate::DeductionFailureInfo to store
+ // template parameter and template argument information.
+ struct DFIParamWithArguments : DFIArguments {
+ TemplateParameter Param;
+ };
}
/// \brief Convert from Sema's representation of template deduction information
@@ -566,6 +575,15 @@ static MakeDeductionFailureInfo(ASTContext &Context,
Result.Data = Info.Param.getOpaqueValue();
break;
+ case Sema::TDK_NonDeducedMismatch: {
+ // FIXME: Should allocate from normal heap so that we can free this later.
+ DFIArguments *Saved = new (Context) DFIArguments;
+ Saved->FirstArg = Info.FirstArg;
+ Saved->SecondArg = Info.SecondArg;
+ Result.Data = Saved;
+ break;
+ }
+
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified: {
// FIXME: Should allocate from normal heap so that we can free this later.
@@ -587,8 +605,11 @@ static MakeDeductionFailureInfo(ASTContext &Context,
}
break;
- case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
+ Result.Data = Info.Expression;
+ break;
+
+ case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
@@ -604,10 +625,12 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_FailedOverloadResolution:
break;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
+ case Sema::TDK_NonDeducedMismatch:
// FIXME: Destroy the data?
Data = 0;
break;
@@ -622,8 +645,7 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
break;
// Unhandled
- case Sema::TDK_NonDeducedMismatch:
- case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
}
@@ -644,6 +666,8 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_SubstitutionFailure:
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
return TemplateParameter();
case Sema::TDK_Incomplete:
@@ -655,8 +679,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
return static_cast<DFIParamWithArguments*>(Data)->Param;
// Unhandled
- case Sema::TDK_NonDeducedMismatch:
- case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
@@ -666,24 +689,25 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
TemplateArgumentList *
OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
- case Sema::TDK_Success:
- case Sema::TDK_Invalid:
- case Sema::TDK_InstantiationDepth:
- case Sema::TDK_TooManyArguments:
- case Sema::TDK_TooFewArguments:
- case Sema::TDK_Incomplete:
- case Sema::TDK_InvalidExplicitArguments:
- case Sema::TDK_Inconsistent:
- case Sema::TDK_Underqualified:
- return 0;
+ case Sema::TDK_Success:
+ case Sema::TDK_Invalid:
+ case Sema::TDK_InstantiationDepth:
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ case Sema::TDK_Incomplete:
+ case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_Inconsistent:
+ case Sema::TDK_Underqualified:
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
+ return 0;
- case Sema::TDK_SubstitutionFailure:
- return static_cast<TemplateArgumentList*>(Data);
+ case Sema::TDK_SubstitutionFailure:
+ return static_cast<TemplateArgumentList*>(Data);
- // Unhandled
- case Sema::TDK_NonDeducedMismatch:
- case Sema::TDK_FailedOverloadResolution:
- break;
+ // Unhandled
+ case Sema::TDK_MiscellaneousDeductionFailure:
+ break;
}
return 0;
@@ -699,15 +723,16 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
+ case Sema::TDK_FailedOverloadResolution:
return 0;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
- return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;
+ case Sema::TDK_NonDeducedMismatch:
+ return &static_cast<DFIArguments*>(Data)->FirstArg;
// Unhandled
- case Sema::TDK_NonDeducedMismatch:
- case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
@@ -725,21 +750,31 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
+ case Sema::TDK_FailedOverloadResolution:
return 0;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
- return &static_cast<DFIParamWithArguments*>(Data)->SecondArg;
+ case Sema::TDK_NonDeducedMismatch:
+ return &static_cast<DFIArguments*>(Data)->SecondArg;
// Unhandled
- case Sema::TDK_NonDeducedMismatch:
- case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
return 0;
}
+Expr *
+OverloadCandidate::DeductionFailureInfo::getExpr() {
+ if (static_cast<Sema::TemplateDeductionResult>(Result) ==
+ Sema::TDK_FailedOverloadResolution)
+ return static_cast<Expr*>(Data);
+
+ return 0;
+}
+
void OverloadCandidateSet::destroyCandidates() {
for (iterator i = begin(), e = end(); i != e; ++i) {
for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
@@ -885,7 +920,8 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
// function templates hide function templates with different
// return types or template parameter lists.
bool UseMemberUsingDeclRules =
- (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord();
+ (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() &&
+ !New->getFriendObjectKind();
if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) {
@@ -929,13 +965,21 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
return Ovl_Overload;
}
-bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
- bool UseUsingDeclRules) {
- // If both of the functions are extern "C", then they are not
- // overloads.
- if (Old->isExternC() && New->isExternC())
+static bool canBeOverloaded(const FunctionDecl &D) {
+ if (D.getAttr<OverloadableAttr>())
+ return true;
+ if (D.isExternC())
+ return false;
+
+ // Main cannot be overloaded (basic.start.main).
+ if (D.isMain())
return false;
+ return true;
+}
+
+static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
+ bool UseUsingDeclRules) {
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
@@ -946,8 +990,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return true;
// Is the function New an overload of the function Old?
- QualType OldQType = Context.getCanonicalType(Old->getType());
- QualType NewQType = Context.getCanonicalType(New->getType());
+ QualType OldQType = S.Context.getCanonicalType(Old->getType());
+ QualType NewQType = S.Context.getCanonicalType(New->getType());
// Compare the signatures (C++ 1.3.10) of the two functions to
// determine whether they are overloads. If we find any mismatch
@@ -968,7 +1012,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
if (OldQType != NewQType &&
(OldType->getNumArgs() != NewType->getNumArgs() ||
OldType->isVariadic() != NewType->isVariadic() ||
- !FunctionArgTypesAreEqual(OldType, NewType)))
+ !S.FunctionArgTypesAreEqual(OldType, NewType)))
return true;
// C++ [temp.over.link]p4:
@@ -984,9 +1028,9 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
// However, we don't consider either of these when deciding whether
// a member introduced by a shadow declaration is hidden.
if (!UseUsingDeclRules && NewTemplate &&
- (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
- OldTemplate->getTemplateParameters(),
- false, TPL_TemplateMatch) ||
+ (!S.TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+ OldTemplate->getTemplateParameters(),
+ false, S.TPL_TemplateMatch) ||
OldType->getResultType() != NewType->getResultType()))
return true;
@@ -998,34 +1042,55 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
// 13.1p2). While not part of the definition of the signature,
// this check is important to determine whether these functions
// can be overloaded.
- CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
- CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+ CXXMethodDecl *OldMethod = dyn_cast<CXXMethodDecl>(Old);
+ CXXMethodDecl *NewMethod = dyn_cast<CXXMethodDecl>(New);
if (OldMethod && NewMethod &&
- !OldMethod->isStatic() && !NewMethod->isStatic() &&
- (OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers() ||
- OldMethod->getRefQualifier() != NewMethod->getRefQualifier())) {
- if (!UseUsingDeclRules &&
- OldMethod->getRefQualifier() != NewMethod->getRefQualifier() &&
- (OldMethod->getRefQualifier() == RQ_None ||
- NewMethod->getRefQualifier() == RQ_None)) {
- // C++0x [over.load]p2:
- // - Member function declarations with the same name and the same
- // parameter-type-list as well as member function template
- // declarations with the same name, the same parameter-type-list, and
- // the same template parameter lists cannot be overloaded if any of
- // them, but not all, have a ref-qualifier (8.3.5).
- Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
- << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
- Diag(OldMethod->getLocation(), diag::note_previous_declaration);
+ !OldMethod->isStatic() && !NewMethod->isStatic()) {
+ if (OldMethod->getRefQualifier() != NewMethod->getRefQualifier()) {
+ if (!UseUsingDeclRules &&
+ (OldMethod->getRefQualifier() == RQ_None ||
+ NewMethod->getRefQualifier() == RQ_None)) {
+ // C++0x [over.load]p2:
+ // - Member function declarations with the same name and the same
+ // parameter-type-list as well as member function template
+ // declarations with the same name, the same parameter-type-list, and
+ // the same template parameter lists cannot be overloaded if any of
+ // them, but not all, have a ref-qualifier (8.3.5).
+ S.Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
+ << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
+ S.Diag(OldMethod->getLocation(), diag::note_previous_declaration);
+ }
+ return true;
}
- return true;
+ // We may not have applied the implicit const for a constexpr member
+ // function yet (because we haven't yet resolved whether this is a static
+ // or non-static member function). Add it now, on the assumption that this
+ // is a redeclaration of OldMethod.
+ unsigned NewQuals = NewMethod->getTypeQualifiers();
+ if (NewMethod->isConstexpr() && !isa<CXXConstructorDecl>(NewMethod))
+ NewQuals |= Qualifiers::Const;
+ if (OldMethod->getTypeQualifiers() != NewQuals)
+ return true;
}
// The signatures match; this is not an overload.
return false;
}
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
+ bool UseUsingDeclRules) {
+ if (!shouldTryToOverload(*this, New, Old, UseUsingDeclRules))
+ return false;
+
+ // If both of the functions are extern "C", then they are not
+ // overloads.
+ if (!canBeOverloaded(*Old) && !canBeOverloaded(*New))
+ return false;
+
+ return true;
+}
+
/// \brief Checks availability of the function depending on the current
/// function context. Inside an unavailable function, unavailability is ignored.
///
@@ -1577,6 +1642,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// tryAtomicConversion has updated the standard conversion sequence
// appropriately.
return true;
+ } else if (ToType->isEventT() &&
+ From->isIntegerConstantExpr(S.getASTContext()) &&
+ (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) {
+ SCS.Second = ICK_Zero_Event_Conversion;
+ FromType = ToType;
} else {
// No second conversion required.
SCS.Second = ICK_Identity;
@@ -1606,9 +1676,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
CanonTo = S.Context.getCanonicalType(ToType);
if (CanonFrom.getLocalUnqualifiedType()
== CanonTo.getLocalUnqualifiedType() &&
- (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()
- || CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr()
- || CanonFrom.getObjCLifetime() != CanonTo.getObjCLifetime())) {
+ CanonFrom.getLocalQualifiers() != CanonTo.getLocalQualifiers()) {
FromType = ToType;
CanonFrom = CanonTo;
}
@@ -1818,7 +1886,8 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
return true;
// Half can be promoted to float.
- if (FromBuiltin->getKind() == BuiltinType::Half &&
+ if (!getLangOpts().NativeHalfType &&
+ FromBuiltin->getKind() == BuiltinType::Half &&
ToBuiltin->getKind() == BuiltinType::Float)
return true;
}
@@ -2880,8 +2949,8 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
bool AllowExplicit) {
- DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = S.LookupConstructors(To);
+ DeclContext::lookup_result R = S.LookupConstructors(To);
+ for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
@@ -2980,7 +3049,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
S.IsDerivedFrom(From->getType(), ToType)))
ConstructorsOnly = true;
- S.RequireCompleteType(From->getLocStart(), ToType, 0);
+ 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.
@@ -3008,8 +3077,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
ListInitializing = true;
}
- DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl);
+ DeclContext::lookup_result R = S.LookupConstructors(ToRecordDecl);
+ for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
@@ -3065,10 +3134,11 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (CXXRecordDecl *FromRecordDecl
= dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
// Add all of the conversion functions as candidates.
- const UnresolvedSetImpl *Conversions
- = FromRecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator>
+ Conversions = FromRecordDecl->getVisibleConversionFunctions();
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
DeclAccessPair FoundDecl = I.getPair();
NamedDecl *D = FoundDecl.getDecl();
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
@@ -3198,7 +3268,7 @@ static ImplicitConversionSequence::CompareKind
compareConversionFunctions(Sema &S,
FunctionDecl *Function1,
FunctionDecl *Function2) {
- if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus0x)
+ if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus11)
return ImplicitConversionSequence::Indistinguishable;
// Objective-C++:
@@ -3868,6 +3938,15 @@ CompareDerivedToBaseConversions(Sema &S,
return ImplicitConversionSequence::Indistinguishable;
}
+/// \brief Determine whether the given type is valid, e.g., it is not an invalid
+/// C++ class.
+static bool isTypeValid(QualType T) {
+ if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
+ return !Record->isInvalidDecl();
+
+ return true;
+}
+
/// CompareReferenceRelationship - Compare the two types T1 and T2 to
/// determine whether they are reference-related,
/// reference-compatible, reference-compatible with added
@@ -3901,7 +3980,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
if (UnqualT1 == UnqualT2) {
// Nothing to do.
} else if (!RequireCompleteType(Loc, OrigT2, 0) &&
- IsDerivedFrom(UnqualT2, UnqualT1))
+ isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
+ IsDerivedFrom(UnqualT2, UnqualT1))
DerivedToBase = true;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
UnqualT2->isObjCObjectOrInterfaceType() &&
@@ -3959,10 +4039,11 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
OverloadCandidateSet CandidateSet(DeclLoc);
- const UnresolvedSetImpl *Conversions
- = T2RecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator>
+ Conversions = T2RecordDecl->getVisibleConversionFunctions();
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -4213,7 +4294,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// allow the use of rvalue references in C++98/03 for the benefit of
// standard library implementors; therefore, we need the xvalue check here.
ICS.Standard.DirectBinding =
- S.getLangOpts().CPlusPlus0x ||
+ S.getLangOpts().CPlusPlus11 ||
(InitCategory.isPRValue() && !T2->isRecordType());
ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
@@ -4374,7 +4455,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
bool toStdInitializerList = false;
QualType X;
if (ToType->isArrayType())
- X = S.Context.getBaseElementType(ToType);
+ X = S.Context.getAsArrayType(ToType)->getElementType();
else
toStdInitializerList = S.isStdInitializerList(ToType, &X);
if (!X.isNull()) {
@@ -4595,7 +4676,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 OrigFromType,
+TryObjectArgumentInitialization(Sema &S, QualType FromType,
Expr::Classification FromClassification,
CXXMethodDecl *Method,
CXXRecordDecl *ActingContext) {
@@ -4611,7 +4692,6 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
ImplicitConversionSequence ICS;
// We need to have an object of class type.
- QualType FromType = OrigFromType;
if (const PointerType *PT = FromType->getAs<PointerType>()) {
FromType = PT->getPointeeType();
@@ -4646,7 +4726,7 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
!= FromTypeCanon.getLocalCVRQualifiers() &&
!ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
ICS.setBad(BadConversionSequence::bad_qualifiers,
- OrigFromType, ImplicitParamType);
+ FromType, ImplicitParamType);
return ICS;
}
@@ -4811,6 +4891,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_Identity:
case ICK_Integral_Promotion:
case ICK_Integral_Conversion:
+ case ICK_Zero_Event_Conversion:
return true;
case ICK_Boolean_Conversion:
@@ -4857,7 +4938,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
llvm::APSInt &Value,
CCEKind CCE) {
- assert(LangOpts.CPlusPlus0x && "converted constant expression outside C++11");
+ assert(LangOpts.CPlusPlus11 && "converted constant expression outside C++11");
assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
if (checkPlaceholderForOverload(*this, From))
@@ -4939,7 +5020,7 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
}
// Check the expression is a constant expression.
- llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
@@ -5104,15 +5185,15 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
// Look for a conversion to an integral or enumeration type.
UnresolvedSet<4> ViableConversions;
UnresolvedSet<4> ExplicitConversions;
- const UnresolvedSetImpl *Conversions
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator> Conversions
= cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
- bool HadMultipleCandidates = (Conversions->size() > 1);
+ bool HadMultipleCandidates
+ = (std::distance(Conversions.first, Conversions.second) > 1);
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end();
- I != E;
- ++I) {
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
if (isIntegralOrEnumerationType(
@@ -5230,7 +5311,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
void
Sema::AddOverloadCandidate(FunctionDecl *Function,
DeclAccessPair FoundDecl,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
@@ -5353,7 +5434,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
/// \brief Add all of the function declarations in the given function set to
/// the overload canddiate set.
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
TemplateArgumentListInfo *ExplicitTemplateArgs) {
@@ -5428,7 +5509,7 @@ void
Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
const FunctionProtoType* Proto
@@ -5532,7 +5613,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
Expr::Classification ObjectClassification,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
if (!CandidateSet.isNewCandidate(MethodTmpl))
@@ -5582,7 +5663,7 @@ void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
if (!CandidateSet.isNewCandidate(FunctionTemplate))
@@ -5816,7 +5897,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
Expr *Object,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet) {
if (!CandidateSet.isNewCandidate(Conversion))
return;
@@ -6286,10 +6367,11 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
return;
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
- const UnresolvedSetImpl *Conversions
- = ClassDecl->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator>
+ Conversions = ClassDecl->getVisibleConversionFunctions();
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = I.getDecl();
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
@@ -6355,11 +6437,12 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
if (!ClassDecl->hasDefinition())
return VRQuals;
- const UnresolvedSetImpl *Conversions =
- ClassDecl->getVisibleConversionFunctions();
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator>
+ Conversions = ClassDecl->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = I.getDecl();
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
@@ -7449,7 +7532,7 @@ public:
S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet);
}
- if (S.getLangOpts().CPlusPlus0x) {
+ if (S.getLangOpts().CPlusPlus11) {
for (BuiltinCandidateTypeSet::iterator
Enum = CandidateTypes[ArgIdx].enumeration_begin(),
EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
@@ -7667,7 +7750,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
bool Operator, SourceLocation Loc,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading) {
@@ -8380,7 +8463,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
case Sema::TDK_SubstitutionFailure: {
// Format the template argument list into the argument string.
- llvm::SmallString<128> TemplateArgString;
+ SmallString<128> TemplateArgString;
if (TemplateArgumentList *Args =
Cand->DeductionFailure.getTemplateArgumentList()) {
TemplateArgString = " ";
@@ -8402,7 +8485,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
// Format the SFINAE diagnostic into the argument string.
// FIXME: Add a general mechanism to include a PartialDiagnostic *'s
// formatted message in another diagnostic.
- llvm::SmallString<128> SFINAEArgString;
+ SmallString<128> SFINAEArgString;
SourceRange R;
if (PDiag) {
SFINAEArgString = ": ";
@@ -8416,10 +8499,25 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
return;
}
+ case Sema::TDK_FailedOverloadResolution: {
+ OverloadExpr::FindResult R =
+ OverloadExpr::find(Cand->DeductionFailure.getExpr());
+ S.Diag(Fn->getLocation(),
+ diag::note_ovl_candidate_failed_overload_resolution)
+ << R.Expression->getName();
+ return;
+ }
+
+ case Sema::TDK_NonDeducedMismatch:
+ // FIXME: Provide a source location to indicate what we couldn't match.
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch)
+ << *Cand->DeductionFailure.getFirstArg()
+ << *Cand->DeductionFailure.getSecondArg();
+ return;
+
// TODO: diagnose these individually, then kill off
// note_ovl_candidate_bad_deduction, which is uselessly vague.
- case Sema::TDK_NonDeducedMismatch:
- case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_MiscellaneousDeductionFailure:
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
MaybeEmitInheritedConstructorNote(S, Fn);
return;
@@ -8597,6 +8695,7 @@ RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_MiscellaneousDeductionFailure:
return 3;
case Sema::TDK_InstantiationDepth:
@@ -8721,7 +8820,7 @@ struct CompareOverloadCandidatesForDisplay {
/// CompleteNonViableCandidate - Normally, overload resolution only
/// computes up to the first. Produces the FixIt set if possible.
void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
- llvm::ArrayRef<Expr *> Args) {
+ ArrayRef<Expr *> Args) {
assert(!Cand->Viable);
// Don't do anything on failures other than bad conversion.
@@ -8809,7 +8908,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
/// set.
void OverloadCandidateSet::NoteCandidates(Sema &S,
OverloadCandidateDisplayKind OCD,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
StringRef Opc,
SourceLocation OpLoc) {
// Sort the candidates by viability and position. Sorting directly would
@@ -9400,7 +9499,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
static void AddOverloadedCallCandidate(Sema &S,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading,
bool KnownValid) {
@@ -9431,7 +9530,7 @@ static void AddOverloadedCallCandidate(Sema &S,
/// \brief Add the overload candidates named by callee and/or found by argument
/// dependent lookup to the given overload set.
void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
- llvm::ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading) {
@@ -9495,7 +9594,7 @@ static bool
DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
const CXXScopeSpec &SS, LookupResult &R,
TemplateArgumentListInfo *ExplicitTemplateArgs,
- llvm::ArrayRef<Expr *> Args) {
+ ArrayRef<Expr *> Args) {
if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty())
return false;
@@ -9536,18 +9635,23 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
SemaRef.FindAssociatedClassesAndNamespaces(FnLoc, Args,
AssociatedNamespaces,
AssociatedClasses);
- // Never suggest declaring a function within namespace 'std'.
Sema::AssociatedNamespaceSet SuggestedNamespaces;
- if (DeclContext *Std = SemaRef.getStdNamespace()) {
- for (Sema::AssociatedNamespaceSet::iterator
- it = AssociatedNamespaces.begin(),
- end = AssociatedNamespaces.end(); it != end; ++it) {
- if (!Std->Encloses(*it))
- SuggestedNamespaces.insert(*it);
- }
- } else {
- // Lacking the 'std::' namespace, use all of the associated namespaces.
- SuggestedNamespaces = AssociatedNamespaces;
+ DeclContext *Std = SemaRef.getStdNamespace();
+ for (Sema::AssociatedNamespaceSet::iterator
+ it = AssociatedNamespaces.begin(),
+ end = AssociatedNamespaces.end(); it != end; ++it) {
+ // Never suggest declaring a function within namespace 'std'.
+ if (Std && Std->Encloses(*it))
+ continue;
+
+ // Never suggest declaring a function within a namespace with a reserved
+ // name, like __gnu_cxx.
+ NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it);
+ if (NS &&
+ NS->getQualifiedNameAsString().find("__") != std::string::npos)
+ continue;
+
+ SuggestedNamespaces.insert(*it);
}
SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup)
@@ -9587,7 +9691,7 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
static bool
DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
SourceLocation OpLoc,
- llvm::ArrayRef<Expr *> Args) {
+ ArrayRef<Expr *> Args) {
DeclarationName OpName =
SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName);
@@ -9827,7 +9931,6 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
switch (OverloadResult) {
case OR_Success: {
FunctionDecl *FDecl = (*Best)->Function;
- SemaRef.MarkFunctionReferenced(Fn->getExprLoc(), FDecl);
SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl);
SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc());
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
@@ -10015,8 +10118,6 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// We matched an overloaded operator. Build a call to that
// operator.
- MarkFunctionReferenced(OpLoc, FnDecl);
-
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
@@ -10040,15 +10141,13 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
Input = InputInit.take();
}
- DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
-
// Determine the result type.
QualType ResultTy = FnDecl->getResultType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
// Build the actual expression node.
- ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
+ ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl,
HadMultipleCandidates, OpLoc);
if (FnExpr.isInvalid())
return ExprError();
@@ -10240,8 +10339,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We matched an overloaded operator. Build a call to that
// operator.
- MarkFunctionReferenced(OpLoc, FnDecl);
-
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
// Best->Access is only meaningful for class members.
@@ -10282,8 +10379,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Args[1] = RHS = Arg1.takeAs<Expr>();
}
- DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
-
// Determine the result type.
QualType ResultTy = FnDecl->getResultType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
@@ -10291,6 +10386,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Build the actual expression node.
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
+ Best->FoundDecl,
HadMultipleCandidates, OpLoc);
if (FnExpr.isInvalid())
return ExprError();
@@ -10304,6 +10400,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
FnDecl))
return ExprError();
+ ArrayRef<const Expr *> ArgsArray(Args, 2);
+ // Cut off the implicit 'this'.
+ if (isa<CXXMethodDecl>(FnDecl))
+ ArgsArray = ArgsArray.slice(1);
+ checkCall(FnDecl, ArgsArray, 0, isa<CXXMethodDecl>(FnDecl), OpLoc,
+ TheCall->getSourceRange(), VariadicDoesNotApply);
+
return MaybeBindToTemporary(TheCall);
} else {
// We matched a built-in operator. Convert the arguments, then
@@ -10376,16 +10479,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (isImplicitlyDeleted(Best->Function)) {
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
Diag(OpLoc, diag::err_ovl_deleted_special_oper)
- << getSpecialMember(Method)
- << BinaryOperator::getOpcodeStr(Opc)
- << getDeletedOrUnavailableSuffix(Best->Function);
+ << Context.getRecordType(Method->getParent())
+ << getSpecialMember(Method);
- if (getSpecialMember(Method) != CXXInvalid) {
- // The user probably meant to call this special member. Just
- // explain why it's deleted.
- NoteDeletedFunction(Method);
- return ExprError();
- }
+ // The user probably meant to call this special member. Just
+ // explain why it's deleted.
+ NoteDeletedFunction(Method);
+ return ExprError();
} else {
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
@@ -10463,10 +10563,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched an overloaded operator. Build a call to that
// operator.
- MarkFunctionReferenced(LLoc, FnDecl);
-
CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl);
- DiagnoseUseOfDecl(Best->FoundDecl, LLoc);
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
@@ -10498,6 +10595,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
DeclarationNameInfo OpLocInfo(OpName, LLoc);
OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
+ Best->FoundDecl,
HadMultipleCandidates,
OpLocInfo.getLoc(),
OpLocInfo.getInfo());
@@ -10715,7 +10813,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
- MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc());
@@ -10880,10 +10977,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// functions for each conversion function declared in an
// accessible base class provided the function is not hidden
// within T by another intervening declaration.
- const UnresolvedSetImpl *Conversions
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator> Conversions
= cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -10989,9 +11087,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
RParenLoc);
}
- MarkFunctionReferenced(LParenLoc, Best->Function);
CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
- DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
// We found an overloaded operator(). Build a CXXOperatorCallExpr
// that calls this method, using Object for the implicit object
@@ -11025,7 +11121,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
DeclarationNameInfo OpLocInfo(
Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc);
OpLocInfo.setCXXOperatorNameRange(SourceRange(LParenLoc, RParenLoc));
- ExprResult NewFn = CreateFunctionRefExpr(*this, Method,
+ ExprResult NewFn = CreateFunctionRefExpr(*this, Method, Best->FoundDecl,
HadMultipleCandidates,
OpLocInfo.getLoc(),
OpLocInfo.getInfo());
@@ -11190,9 +11286,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
return ExprError();
}
- MarkFunctionReferenced(OpLoc, Best->Function);
CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
- DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
// Convert the object parameter.
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
@@ -11204,7 +11298,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
Base = BaseResult.take();
// Build the operator call.
- ExprResult FnExpr = CreateFunctionRefExpr(*this, Method,
+ ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, Best->FoundDecl,
HadMultipleCandidates, OpLoc);
if (FnExpr.isInvalid())
return ExprError();
@@ -11259,10 +11353,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
}
FunctionDecl *FD = Best->Function;
- MarkFunctionReferenced(UDSuffixLoc, FD);
- DiagnoseUseOfDecl(Best->FoundDecl, UDSuffixLoc);
-
- ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates,
+ ExprResult Fn = CreateFunctionRefExpr(*this, FD, Best->FoundDecl,
+ HadMultipleCandidates,
SuffixInfo.getLoc(),
SuffixInfo.getInfo());
if (Fn.isInvalid())
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index a8d75b290f19..b135507b1ac0 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -31,10 +31,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/Initialization.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;
@@ -113,7 +114,7 @@ namespace {
Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
// Fortunately, the constraint that we're rebuilding something
// with a base limits the number of cases here.
- assert(refExpr->getBase());
+ assert(refExpr->isObjectReceiver());
if (refExpr->isExplicitProperty()) {
return new (S.Context)
@@ -562,8 +563,9 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) {
if (const ObjCInterfaceDecl *IFace =
dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
const StringRef thisPropertyName(prop->getName());
+ // Try flipping the case of the first character.
char front = thisPropertyName.front();
- front = islower(front) ? toupper(front) : tolower(front);
+ front = isLowercase(front) ? toUppercase(front) : toLowercase(front);
SmallString<100> PropertyName = thisPropertyName;
PropertyName[0] = front;
IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName);
@@ -713,10 +715,9 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
// Explicit properties always have getters, but implicit ones don't.
// Check that before proceeding.
- if (RefExpr->isImplicitProperty() &&
- !RefExpr->getImplicitPropertyGetter()) {
+ if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) {
S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
- << RefExpr->getBase()->getType();
+ << RefExpr->getSourceRange();
return ExprError();
}
@@ -954,16 +955,15 @@ Sema::ObjCSubscriptKind
// objective-C pointer type.
UnresolvedSet<4> ViableConversions;
UnresolvedSet<4> ExplicitConversions;
- const UnresolvedSetImpl *Conversions
+ std::pair<CXXRecordDecl::conversion_iterator,
+ CXXRecordDecl::conversion_iterator> Conversions
= cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
int NoIntegrals=0, NoObjCIdPointers=0;
SmallVector<CXXConversionDecl *, 4> ConversionDecls;
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end();
- I != E;
- ++I) {
+ for (CXXRecordDecl::conversion_iterator
+ I = Conversions.first, E = Conversions.second; I != E; ++I) {
if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
QualType CT = Conversion->getConversionType().getNonReferenceType();
@@ -1087,7 +1087,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
: S.Context.getObjCIdType(),
/*TInfo=*/0,
SC_None,
- SC_None,
0);
AtIndexGetter->setMethodParams(S.Context, Argument,
ArrayRef<SourceLocation>());
@@ -1202,7 +1201,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
S.Context.getObjCIdType(),
/*TInfo=*/0,
SC_None,
- SC_None,
0);
Params.push_back(object);
ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
@@ -1213,7 +1211,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
: S.Context.getObjCIdType(),
/*TInfo=*/0,
SC_None,
- SC_None,
0);
Params.push_back(key);
AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>());
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index f55174e05cc1..ff1db821b658 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -12,21 +12,22 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -35,9 +36,13 @@
using namespace clang;
using namespace sema;
-StmtResult Sema::ActOnExprStmt(FullExprArg expr) {
- Expr *E = expr.get();
- if (!E) // FIXME: FullExprArg has no error state?
+StmtResult Sema::ActOnExprStmt(ExprResult FE) {
+ if (FE.isInvalid())
+ return StmtError();
+
+ FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(),
+ /*DiscardedValue*/ true);
+ if (FE.isInvalid())
return StmtError();
// C99 6.8.3p2: The expression in an expression statement is evaluated as a
@@ -45,10 +50,15 @@ StmtResult Sema::ActOnExprStmt(FullExprArg expr) {
// operand, even incomplete types.
// Same thing in for stmt first clause (when expr) and third clause.
- return Owned(static_cast<Stmt*>(E));
+ return Owned(static_cast<Stmt*>(FE.take()));
}
+StmtResult Sema::ActOnExprStmtError() {
+ DiscardCleanupsInEvaluationContext();
+ return StmtError();
+}
+
StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc,
bool HasLeadingEmptyMacro) {
return Owned(new (Context) NullStmt(SemiLoc, HasLeadingEmptyMacro));
@@ -125,7 +135,7 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
// Suppress warnings when the operator, suspicious as it may be, comes from
// a macro expansion.
- if (Loc.isMacroID())
+ if (S.SourceMgr.isMacroBodyExpansion(Loc))
return false;
S.Diag(Loc, diag::warn_unused_comparison)
@@ -152,12 +162,20 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
const Expr *E = dyn_cast_or_null<Expr>(S);
if (!E)
return;
+ SourceLocation ExprLoc = E->IgnoreParens()->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,
+ // we warn no matter the location. Because of the order in which the various
+ // checks need to happen, we factor out the macro-related test here.
+ bool ShouldSuppress =
+ SourceMgr.isMacroBodyExpansion(ExprLoc) ||
+ SourceMgr.isInSystemMacro(ExprLoc);
const Expr *WarnExpr;
SourceLocation Loc;
SourceRange R1, R2;
- if (SourceMgr.isInSystemMacro(E->getExprLoc()) ||
- !E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context))
+ if (!E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context))
return;
// If this is a GNU statement expression expanded from a macro, it is probably
@@ -185,12 +203,16 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
return;
// If the callee has attribute pure, const, or warn_unused_result, warn with
- // a more specific message to make it clear what is happening.
+ // a more specific message to make it clear what is happening. If the call
+ // is written in a macro body, only warn if it has the warn_unused_result
+ // attribute.
if (const Decl *FD = CE->getCalleeDecl()) {
if (FD->getAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
return;
}
+ if (ShouldSuppress)
+ return;
if (FD->getAttr<PureAttr>()) {
Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
return;
@@ -200,7 +222,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
return;
}
}
- } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
+ } else if (ShouldSuppress)
+ return;
+
+ if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
if (getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) {
Diag(Loc, diag::err_arc_unused_init_message) << R1;
return;
@@ -229,7 +254,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
// We really do want to use the non-canonical type here.
if (T == Context.VoidPtrTy) {
- PointerTypeLoc TL = cast<PointerTypeLoc>(TI->getTypeLoc());
+ PointerTypeLoc TL = TI->getTypeLoc().castAs<PointerTypeLoc>();
Diag(Loc, diag::warn_unused_voidptr)
<< FixItHint::CreateRemoval(TL.getStarLoc());
@@ -298,7 +323,9 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]);
}
- return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R));
+ return Owned(new (Context) CompoundStmt(Context,
+ llvm::makeArrayRef(Elts, NumElts),
+ L, R));
}
StmtResult
@@ -312,7 +339,7 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
return StmtError();
}
- if (!getLangOpts().CPlusPlus0x) {
+ if (!getLangOpts().CPlusPlus11) {
// C99 6.8.4.2p3: The expression shall be an integer constant.
// However, GCC allows any evaluatable integer expression.
if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) {
@@ -328,6 +355,12 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
// Recover from an error by just forgetting about it.
}
}
+
+ LHSVal = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
+ getLangOpts().CPlusPlus11).take();
+ if (RHSVal)
+ RHSVal = ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false,
+ getLangOpts().CPlusPlus11).take();
CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
ColonLoc);
@@ -390,6 +423,13 @@ 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 = 0;
@@ -595,8 +635,7 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
Cond = CondResult.take();
if (!CondVar) {
- CheckImplicitConversions(Cond, SwitchLoc);
- CondResult = MaybeCreateExprWithCleanups(Cond);
+ CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);
if (CondResult.isInvalid())
return StmtError();
Cond = CondResult.take();
@@ -710,7 +749,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
llvm::APSInt LoVal;
- if (getLangOpts().CPlusPlus0x) {
+ if (getLangOpts().CPlusPlus11) {
// C++11 [stmt.switch]p2: the constant-expression shall be a converted
// constant expression of the promoted type of the switch condition.
ExprResult ConvLo =
@@ -792,7 +831,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(CurrCase)) {
CurrString = DeclRef->getDecl()->getName();
}
- llvm::SmallString<16> CaseValStr;
+ SmallString<16> CaseValStr;
CaseVals[i-1].first.toString(CaseValStr);
if (PrevString == CurrString)
@@ -830,7 +869,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Expr *Hi = CR->getRHS();
llvm::APSInt HiVal;
- if (getLangOpts().CPlusPlus0x) {
+ if (getLangOpts().CPlusPlus11) {
// C++11 [stmt.switch]p2: the constant-expression shall be a converted
// constant expression of the promoted type of the switch condition.
ExprResult ConvHi =
@@ -1149,12 +1188,11 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
assert(Cond && "ActOnDoStmt(): missing expression");
ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc);
- if (CondResult.isInvalid() || CondResult.isInvalid())
+ if (CondResult.isInvalid())
return StmtError();
Cond = CondResult.take();
- CheckImplicitConversions(Cond, DoLoc);
- CondResult = MaybeCreateExprWithCleanups(Cond);
+ CondResult = ActOnFinishFullExpr(Cond, DoLoc);
if (CondResult.isInvalid())
return StmtError();
Cond = CondResult.take();
@@ -1170,13 +1208,13 @@ namespace {
// of the excluded constructs are used.
class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> {
llvm::SmallPtrSet<VarDecl*, 8> &Decls;
- llvm::SmallVector<SourceRange, 10> &Ranges;
+ SmallVector<SourceRange, 10> &Ranges;
bool Simple;
public:
typedef EvaluatedExprVisitor<DeclExtractor> Inherited;
DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls,
- llvm::SmallVector<SourceRange, 10> &Ranges) :
+ SmallVector<SourceRange, 10> &Ranges) :
Inherited(S.Context),
Decls(Decls),
Ranges(Ranges),
@@ -1325,7 +1363,7 @@ public:
PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body);
llvm::SmallPtrSet<VarDecl*, 8> Decls;
- llvm::SmallVector<SourceRange, 10> Ranges;
+ SmallVector<SourceRange, 10> Ranges;
DeclExtractor DE(S, Decls, Ranges);
DE.Visit(Second);
@@ -1361,8 +1399,8 @@ public:
// Load SourceRanges into diagnostic if there is room.
// Otherwise, load the SourceRange of the conditional expression.
if (Ranges.size() <= PartialDiagnostic::MaxArguments)
- for (llvm::SmallVector<SourceRange, 10>::iterator I = Ranges.begin(),
- E = Ranges.end();
+ for (SmallVector<SourceRange, 10>::iterator I = Ranges.begin(),
+ E = Ranges.end();
I != E; ++I)
PDiag << *I;
else
@@ -1432,12 +1470,10 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
if (result.isInvalid()) return StmtError();
E = result.take();
- CheckImplicitConversions(E);
-
- result = MaybeCreateExprWithCleanups(E);
- if (result.isInvalid()) return StmtError();
-
- return Owned(static_cast<Stmt*>(result.take()));
+ ExprResult FullExpr = ActOnFinishFullExpr(E);
+ if (FullExpr.isInvalid())
+ return StmtError();
+ return StmtResult(static_cast<Stmt*>(FullExpr.take()));
}
ExprResult
@@ -1508,7 +1544,7 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
}
// Wrap up any cleanups in the expression.
- return Owned(MaybeCreateExprWithCleanups(collection));
+ return Owned(collection);
}
StmtResult
@@ -1553,6 +1589,10 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
if (CollectionExprResult.isInvalid())
return StmtError();
+ CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.take());
+ if (CollectionExprResult.isInvalid())
+ return StmtError();
+
return Owned(new (Context) ObjCForCollectionStmt(First,
CollectionExprResult.take(), 0,
ForLoc, RParenLoc));
@@ -1625,7 +1665,7 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
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_Auto, SC_None);
+ TInfo, SC_None);
Decl->setImplicit();
return Decl;
}
@@ -1937,8 +1977,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get();
Diag(Range->getLocStart(), diag::err_for_range_invalid)
<< RangeLoc << Range->getType() << BEFFailure;
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
- llvm::makeArrayRef(&Range, /*NumArgs=*/1));
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Range);
}
// Return an error if no fix was discovered.
if (RangeStatus != FRS_Success)
@@ -2096,9 +2135,13 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
E = ExprRes.take();
if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
return StmtError();
- E = MaybeCreateExprWithCleanups(E);
}
+ ExprResult ExprRes = ActOnFinishFullExpr(E);
+ if (ExprRes.isInvalid())
+ return StmtError();
+ E = ExprRes.take();
+
getCurFunction()->setHasIndirectGoto();
return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
@@ -2370,8 +2413,10 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
if (RetValExp) {
- CheckImplicitConversions(RetValExp, ReturnLoc);
- RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+ ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
+ if (ER.isInvalid())
+ return StmtError();
+ RetValExp = ER.take();
}
ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp,
NRVOCandidate);
@@ -2400,8 +2445,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
QualType RelatedRetType;
if (const FunctionDecl *FD = getCurFunctionDecl()) {
FnRetType = FD->getResultType();
- if (FD->hasAttr<NoReturnAttr>() ||
- FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
+ if (FD->isNoReturn())
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
<< FD->getDeclName();
} else if (ObjCMethodDecl *MD = getCurMethodDecl()) {
@@ -2473,8 +2517,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
if (RetValExp) {
- CheckImplicitConversions(RetValExp, ReturnLoc);
- RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+ ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
+ if (ER.isInvalid())
+ return StmtError();
+ RetValExp = ER.take();
}
}
@@ -2490,24 +2536,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
Result = new (Context) ReturnStmt(ReturnLoc);
} else {
+ assert(RetValExp || FnRetType->isDependentType());
const VarDecl *NRVOCandidate = 0;
if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
// we have a non-void function with an expression, continue checking
- if (!RelatedRetType.isNull()) {
- // If we have a related result type, perform an extra conversion here.
- // FIXME: The diagnostics here don't really describe what is happening.
- InitializedEntity Entity =
- InitializedEntity::InitializeTemporary(RelatedRetType);
-
- ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(),
- RetValExp);
- if (Res.isInvalid()) {
- // FIXME: Cleanup temporaries here, anyway?
- return StmtError();
- }
- RetValExp = Res.takeAs<Expr>();
- }
+ QualType RetType = (RelatedRetType.isNull() ? FnRetType : RelatedRetType);
// C99 6.8.6.4p3(136): The return statement is not an assignment. The
// overlap restriction of subclause 6.5.16.1 does not apply to the case of
@@ -2517,23 +2551,40 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// the C version of which boils down to CheckSingleAssignmentConstraints.
NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
- FnRetType,
+ RetType,
NRVOCandidate != 0);
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
- FnRetType, RetValExp);
+ RetType, RetValExp);
if (Res.isInvalid()) {
- // FIXME: Cleanup temporaries here, anyway?
+ // FIXME: Clean up temporaries here anyway?
return StmtError();
}
-
RetValExp = Res.takeAs<Expr>();
- if (RetValExp)
- CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+
+ // If we have a related result type, we need to implicitly
+ // convert back to the formal result type. We can't pretend to
+ // initialize the result again --- we might end double-retaining
+ // --- so instead we initialize a notional temporary; this can
+ // lead to less-than-great diagnostics, but this stage is much
+ // less likely to fail than the previous stage.
+ if (!RelatedRetType.isNull()) {
+ Entity = InitializedEntity::InitializeTemporary(FnRetType);
+ Res = PerformCopyInitialization(Entity, ReturnLoc, RetValExp);
+ if (Res.isInvalid()) {
+ // FIXME: Clean up temporaries here anyway?
+ return StmtError();
+ }
+ RetValExp = Res.takeAs<Expr>();
+ }
+
+ CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
}
if (RetValExp) {
- CheckImplicitConversions(RetValExp, ReturnLoc);
- RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+ ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
+ if (ER.isInvalid())
+ return StmtError();
+ RetValExp = ER.take();
}
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
}
@@ -2583,7 +2634,11 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
if (Result.isInvalid())
return StmtError();
- Throw = MaybeCreateExprWithCleanups(Result.take());
+ Result = ActOnFinishFullExpr(Result.take());
+ if (Result.isInvalid())
+ return StmtError();
+ Throw = Result.take();
+
QualType ThrowType = Throw->getType();
// Make sure the expression type is an ObjC pointer or "void *".
if (!ThrowType->isDependentType() &&
@@ -2634,7 +2689,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) {
}
// The operand to @synchronized is a full-expression.
- return MaybeCreateExprWithCleanups(operand);
+ return ActOnFinishFullExpr(operand);
}
StmtResult
@@ -2756,7 +2811,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
// and warns.
return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock,
- Handlers, NumHandlers));
+ llvm::makeArrayRef(Handlers, NumHandlers)));
}
StmtResult
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 7c2c766e4615..da33bdf717e6 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -12,25 +12,25 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -124,11 +124,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
// Check that the output exprs are valid lvalues.
Expr *OutputExpr = Exprs[i];
- if (CheckAsmLValue(OutputExpr, *this)) {
+ if (CheckAsmLValue(OutputExpr, *this))
return StmtError(Diag(OutputExpr->getLocStart(),
- diag::err_asm_invalid_lvalue_in_output)
- << OutputExpr->getSourceRange());
- }
+ diag::err_asm_invalid_lvalue_in_output)
+ << OutputExpr->getSourceRange());
+
+ if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
+ diag::err_dereference_incomplete_type))
+ return StmtError();
OutputConstraintInfos.push_back(Info);
}
@@ -179,6 +182,22 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
Exprs[i] = Result.take();
InputConstraintInfos.push_back(Info);
+
+ const Type *Ty = Exprs[i]->getType().getTypePtr();
+ if (Ty->isDependentType())
+ continue;
+
+ if (!Ty->isVoidType() || !Info.allowsMemory())
+ if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(),
+ diag::err_dereference_incomplete_type))
+ return StmtError();
+
+ unsigned Size = Context.getTypeSize(Ty);
+ if (!Context.getTargetInfo().validateInputSize(Literal->getString(),
+ Size))
+ return StmtError(Diag(InputExpr->getLocStart(),
+ diag::err_asm_invalid_input_size)
+ << Info.getConstraintStr());
}
// Check that the clobbers are valid.
@@ -377,7 +396,7 @@ static StringRef getSpelling(Sema &SemaRef, Token AsmTok) {
static bool buildMSAsmString(Sema &SemaRef,
SourceLocation AsmLoc,
ArrayRef<Token> AsmToks,
- llvm::SmallVectorImpl<unsigned> &TokOffsets,
+ SmallVectorImpl<unsigned> &TokOffsets,
std::string &AsmString) {
assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
@@ -426,9 +445,14 @@ public:
: SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { }
~MCAsmParserSemaCallbackImpl() {}
- void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, unsigned &Size){
+ void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc,
+ unsigned &Length, unsigned &Size,
+ unsigned &Type, bool &IsVarDecl){
SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc);
- NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Size);
+
+ NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Length,
+ Size, Type,
+ IsVarDecl);
return static_cast<void *>(OpDecl);
}
@@ -471,8 +495,12 @@ public:
}
NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc,
- unsigned &Size) {
+ unsigned &Length, unsigned &Size,
+ unsigned &Type, bool &IsVarDecl) {
+ Length = 1;
Size = 0;
+ Type = 0;
+ IsVarDecl = false;
LookupResult Result(*this, &Context.Idents.get(Name), Loc,
Sema::LookupOrdinaryName);
@@ -487,12 +515,19 @@ NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc,
return 0;
}
- NamedDecl *ND = Result.getFoundDecl();
- if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
- if (VarDecl *Var = dyn_cast<VarDecl>(ND))
- Size = Context.getTypeInfo(Var->getType()).first;
-
- return ND;
+ NamedDecl *FoundDecl = Result.getFoundDecl();
+ if (isa<FunctionDecl>(FoundDecl))
+ return FoundDecl;
+ if (VarDecl *Var = dyn_cast<VarDecl>(FoundDecl)) {
+ QualType Ty = Var->getType();
+ Type = Size = Context.getTypeSizeInChars(Ty).getQuantity();
+ if (Ty->isArrayType()) {
+ const ArrayType *ATy = Context.getAsArrayType(Ty);
+ Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
+ Length = Size / Type;
+ }
+ IsVarDecl = true;
+ return FoundDecl;
}
// FIXME: Handle other kinds of results? (FieldDecl, etc.)
@@ -512,13 +547,12 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
if (!BaseResult.isSingleResult())
return true;
- NamedDecl *FoundDecl = BaseResult.getFoundDecl();
const RecordType *RT = 0;
- if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) {
+ NamedDecl *FoundDecl = BaseResult.getFoundDecl();
+ if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
RT = VD->getType()->getAs<RecordType>();
- } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl)) {
+ else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl))
RT = TD->getUnderlyingType()->getAs<RecordType>();
- }
if (!RT)
return true;
@@ -551,8 +585,15 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
SmallVector<Expr*, 4> Exprs;
SmallVector<StringRef, 4> ClobberRefs;
+ llvm::Triple TheTriple = Context.getTargetInfo().getTriple();
+ llvm::Triple::ArchType ArchTy = TheTriple.getArch();
+ bool UnsupportedArch = ArchTy != llvm::Triple::x86 &&
+ ArchTy != llvm::Triple::x86_64;
+ if (UnsupportedArch)
+ Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName();
+
// Empty asm statements don't need to instantiate the AsmParser, etc.
- if (AsmToks.empty()) {
+ if (UnsupportedArch || AsmToks.empty()) {
StringRef EmptyAsmStr;
MSAsmStmt *NS =
new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
@@ -563,13 +604,13 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
}
std::string AsmString;
- llvm::SmallVector<unsigned, 8> TokOffsets;
+ SmallVector<unsigned, 8> TokOffsets;
if (buildMSAsmString(*this, AsmLoc, AsmToks, TokOffsets, AsmString))
return StmtError();
// Get the target specific parser.
std::string Error;
- const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
+ const std::string &TT = TheTriple.getTriple();
const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));
OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
@@ -614,7 +655,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
SmallVector<std::pair<void *, bool>, 4> OpDecls;
SmallVector<std::string, 4> Constraints;
SmallVector<std::string, 4> Clobbers;
- if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR,
+ if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR,
NumOutputs, NumInputs, OpDecls, Constraints,
Clobbers, MII, IP, MCAPSI))
return StmtError();
@@ -641,7 +682,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
if (OpExpr.isInvalid())
return StmtError();
- // Need offset of variable.
+ // Need address of variable.
if (OpDecls[i].second)
OpExpr = BuildUnaryOp(getCurScope(), AsmLoc, clang::UO_AddrOf,
OpExpr.take());
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index b268b4502c4f..eb0188a0db3d 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -58,8 +58,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
default:
// if we're here, then we parsed a known attribute, but didn't recognize
// it as a statement attribute => it is declaration attribute
- S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt)
- << A.getName()->getName() << St->getLocStart();
+ S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
+ << A.getName() << St->getLocStart();
return 0;
}
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index f56b05406d07..990626189e18 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -9,23 +9,23 @@
// This file implements semantic analysis for C++ templates.
//===----------------------------------------------------------------------===/
-#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/Template.h"
-#include "clang/Sema/TemplateDeduction.h"
#include "TreeTransform.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeVisitor.h"
-#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/ParsedTemplate.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -356,7 +356,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope &&
- !(getLangOpts().CPlusPlus0x && !Found.empty())) {
+ !(getLangOpts().CPlusPlus11 && !Found.empty())) {
// C++03 [basic.lookup.classref]p1:
// [...] If the lookup in the class of the object expression finds a
// template, the name is also looked up in the context of the entire
@@ -510,7 +510,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
TemplateName Template = Arg.getAsTemplate().get();
TemplateArgument TArg;
if (Arg.getEllipsisLoc().isValid())
- TArg = TemplateArgument(Template, llvm::Optional<unsigned int>());
+ TArg = TemplateArgument(Template, Optional<unsigned int>());
else
TArg = Template;
return TemplateArgumentLoc(TArg,
@@ -1171,7 +1171,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
// template-argument, that declaration shall be a definition and shall be
// the only declaration of the function template in the translation unit.
// (C++98/03 doesn't have this wording; see DR226).
- S.Diag(ParamLoc, S.getLangOpts().CPlusPlus0x ?
+ S.Diag(ParamLoc, S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_parameter_default_in_function_template
: diag::ext_template_parameter_default_in_function_template)
<< DefArgRange;
@@ -2359,7 +2359,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
TemplateTy &Result) {
if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TemplateKWLoc,
- getLangOpts().CPlusPlus0x ?
+ getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_outside_of_template :
diag::ext_template_outside_of_template)
<< FixItHint::CreateRemoval(TemplateKWLoc);
@@ -2387,7 +2387,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
// "template" keyword is now permitted). We follow the C++0x
// rules, even in C++03 mode with a warning, retroactively applying the DR.
bool MemberOfUnknownSpecialization;
- TemplateNameKind TNK = isTemplateName(0, SS, TemplateKWLoc.isValid(), Name,
+ TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name,
ObjectType, EnteringContext, Result,
MemberOfUnknownSpecialization);
if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
@@ -2972,7 +2972,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// We have a template template parameter but the template
// argument does not refer to a template.
Diag(Arg.getLocation(), diag::err_template_arg_must_be_template)
- << getLangOpts().CPlusPlus0x;
+ << getLangOpts().CPlusPlus11;
return true;
case TemplateArgument::Declaration:
@@ -3023,7 +3023,7 @@ static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template,
///
/// In \c A<int,int>::B, \c NTs and \c TTs have expanded pack size 2, and \c Us
/// is not a pack expansion, so returns an empty Optional.
-static llvm::Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
+static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (NTTP->isExpandedParameterPack())
@@ -3036,7 +3036,7 @@ static llvm::Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
return TTP->getNumExpansionTemplateParameters();
}
- return llvm::Optional<unsigned>();
+ return None;
}
/// \brief Check that the given template argument list is well-formed
@@ -3068,7 +3068,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
Param != ParamEnd; /* increment in loop */) {
// If we have an expanded parameter pack, make sure we don't have too
// many arguments.
- if (llvm::Optional<unsigned> Expansions = getExpandedPackSize(*Param)) {
+ if (Optional<unsigned> Expansions = getExpandedPackSize(*Param)) {
if (*Expansions == ArgumentPack.size()) {
// We're done with this parameter pack. Pack up its arguments and add
// them to the list.
@@ -3486,16 +3486,16 @@ bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
if (Tag->getDeclContext()->isFunctionOrMethod()) {
S.Diag(SR.getBegin(),
- S.getLangOpts().CPlusPlus0x ?
+ S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_local_type :
diag::ext_template_arg_local_type)
<< S.Context.getTypeDeclType(Tag) << SR;
return true;
}
- if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) {
+ if (!Tag->hasNameForLinkage()) {
S.Diag(SR.getBegin(),
- S.getLangOpts().CPlusPlus0x ?
+ S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_unnamed_type :
diag::ext_template_arg_unnamed_type) << SR;
S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here);
@@ -3549,7 +3549,7 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
//
// C++11 allows these, and even in C++03 we allow them as an extension with
// a warning.
- if (LangOpts.CPlusPlus0x ?
+ if (LangOpts.CPlusPlus11 ?
Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_unnamed_type,
SR.getBegin()) != DiagnosticsEngine::Ignored ||
Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_local_type,
@@ -3576,7 +3576,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
if (Arg->isValueDependent() || Arg->isTypeDependent())
return NPV_NotNullPointer;
- if (!S.getLangOpts().CPlusPlus0x)
+ if (!S.getLangOpts().CPlusPlus11)
return NPV_NotNullPointer;
// Determine whether we have a constant expression.
@@ -3586,7 +3586,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
Arg = ArgRV.take();
Expr::EvalResult EvalResult;
- llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ SmallVector<PartialDiagnosticAt, 8> Notes;
EvalResult.Diag = &Notes;
if (!Arg->EvaluateAsRValue(EvalResult, S.Context) ||
EvalResult.HasSideEffects) {
@@ -3704,7 +3704,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
if (!Invalid && !ExtraParens) {
S.Diag(Arg->getLocStart(),
- S.getLangOpts().CPlusPlus0x ?
+ S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_extra_parens :
diag::ext_template_arg_extra_parens)
<< Arg->getSourceRange();
@@ -3794,7 +3794,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// Address / reference template args must have external linkage in C++98.
if (Entity->getLinkage() == InternalLinkage) {
- S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus0x ?
+ S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_object_internal :
diag::ext_template_arg_object_internal)
<< !Func << Entity << Arg->getSourceRange();
@@ -3950,7 +3950,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// Create the template argument.
Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
ParamType->isReferenceType());
- S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity);
+ S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity, false);
return false;
}
@@ -4010,7 +4010,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
if (!Invalid && !ExtraParens) {
S.Diag(Arg->getLocStart(),
- S.getLangOpts().CPlusPlus0x ?
+ S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_extra_parens :
diag::ext_template_arg_extra_parens)
<< Arg->getSourceRange();
@@ -4139,7 +4139,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return ExprError();
}
- if (getLangOpts().CPlusPlus0x) {
+ if (getLangOpts().CPlusPlus11) {
// We can't check arbitrary value-dependent arguments.
// FIXME: If there's no viable conversion to the template parameter type,
// we should be able to diagnose that prior to instantiation.
@@ -4495,6 +4495,16 @@ ExprResult
Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
QualType ParamType,
SourceLocation Loc) {
+ // C++ [temp.param]p8:
+ //
+ // A non-type template-parameter of type "array of T" or
+ // "function returning T" is adjusted to be of type "pointer to
+ // T" or "pointer to function returning T", respectively.
+ if (ParamType->isArrayType())
+ ParamType = Context.getArrayDecayedType(ParamType);
+ else if (ParamType->isFunctionType())
+ ParamType = Context.getPointerType(ParamType);
+
// For a NULL non-type template argument, return nullptr casted to the
// parameter's type.
if (Arg.getKind() == TemplateArgument::NullPtr) {
@@ -4560,6 +4570,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
}
QualType T = VD->getType().getNonReferenceType();
+
if (ParamType->isPointerType()) {
// When the non-type template parameter is a pointer, take the
// address of the declaration.
@@ -4589,6 +4600,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
VK = VK_LValue;
T = Context.getQualifiedType(T,
TargetRef->getPointeeType().getQualifiers());
+ } else if (isa<FunctionDecl>(VD)) {
+ // References to functions are always lvalues.
+ VK = VK_LValue;
}
return BuildDeclRefExpr(VD, T, VK, Loc);
@@ -4606,7 +4620,18 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc) {
assert(Arg.getKind() == TemplateArgument::Integral &&
"Operation is only valid for integral template arguments");
- QualType T = Arg.getIntegralType();
+ QualType OrigT = Arg.getIntegralType();
+
+ // If this is an enum type that we're instantiating, we need to use an integer
+ // type the same size as the enumerator. We don't want to build an
+ // IntegerLiteral with enum type. The integer type of an enum type can be of
+ // any integral type with C++11 enum classes, make sure we create the right
+ // type of literal for it.
+ QualType T = OrigT;
+ if (const EnumType *ET = OrigT->getAs<EnumType>())
+ T = ET->getDecl()->getIntegerType();
+
+ Expr *E;
if (T->isAnyCharacterType()) {
CharacterLiteral::CharacterKind Kind;
if (T->isWideCharType())
@@ -4618,34 +4643,22 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
else
Kind = CharacterLiteral::Ascii;
- return Owned(new (Context) CharacterLiteral(
- Arg.getAsIntegral().getZExtValue(),
- Kind, T, Loc));
+ E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(),
+ Kind, T, Loc);
+ } else if (T->isBooleanType()) {
+ E = new (Context) CXXBoolLiteralExpr(Arg.getAsIntegral().getBoolValue(),
+ T, Loc);
+ } else if (T->isNullPtrType()) {
+ E = new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc);
+ } else {
+ E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), T, Loc);
}
- if (T->isBooleanType())
- return Owned(new (Context) CXXBoolLiteralExpr(
- Arg.getAsIntegral().getBoolValue(),
- T, Loc));
-
- if (T->isNullPtrType())
- return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
-
- // If this is an enum type that we're instantiating, we need to use an integer
- // type the same size as the enumerator. We don't want to build an
- // IntegerLiteral with enum type.
- QualType BT;
- if (const EnumType *ET = T->getAs<EnumType>())
- BT = ET->getDecl()->getIntegerType();
- else
- BT = T;
-
- Expr *E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), BT, Loc);
- if (T->isEnumeralType()) {
+ if (OrigT->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
- E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0,
- Context.getTrivialTypeSourceInfo(T, Loc),
+ E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E, 0,
+ Context.getTrivialTypeSourceInfo(OrigT, Loc),
Loc, Loc);
}
@@ -4961,11 +4974,11 @@ static bool CheckTemplateSpecializationScope(Sema &S,
EntityKind = 4;
else if (isa<RecordDecl>(Specialized))
EntityKind = 5;
- else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus0x)
+ else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus11)
EntityKind = 6;
else {
S.Diag(Loc, diag::err_template_spec_unknown_kind)
- << S.getLangOpts().CPlusPlus0x;
+ << S.getLangOpts().CPlusPlus11;
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
return true;
}
@@ -5036,17 +5049,17 @@ static bool CheckTemplateSpecializationScope(Sema &S,
// An explicit specialization shall be declared in a namespace enclosing
// the specialized template.
if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
- bool IsCPlusPlus0xExtension = DC->Encloses(SpecializedContext);
+ bool IsCPlusPlus11Extension = DC->Encloses(SpecializedContext);
if (isa<TranslationUnitDecl>(SpecializedContext)) {
- assert(!IsCPlusPlus0xExtension &&
+ assert(!IsCPlusPlus11Extension &&
"DC encloses TU but isn't in enclosing namespace set");
S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
<< EntityKind << Specialized;
} else if (isa<NamespaceDecl>(SpecializedContext)) {
int Diag;
- if (!IsCPlusPlus0xExtension)
+ if (!IsCPlusPlus11Extension)
Diag = diag::err_template_spec_decl_out_of_scope;
- else if (!S.getLangOpts().CPlusPlus0x)
+ else if (!S.getLangOpts().CPlusPlus11)
Diag = diag::ext_template_spec_decl_out_of_scope;
else
Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope;
@@ -5056,7 +5069,7 @@ static bool CheckTemplateSpecializationScope(Sema &S,
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
ComplainedAboutScope =
- !(IsCPlusPlus0xExtension && S.getLangOpts().CPlusPlus0x);
+ !(IsCPlusPlus11Extension && S.getLangOpts().CPlusPlus11);
}
}
@@ -5629,23 +5642,21 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
D.setFunctionDefinitionKind(FDK_Definition);
Decl *DP = HandleDeclarator(ParentScope, D,
TemplateParameterLists);
- if (FunctionTemplateDecl *FunctionTemplate
- = dyn_cast_or_null<FunctionTemplateDecl>(DP))
- return ActOnStartOfFunctionDef(FnBodyScope,
- FunctionTemplate->getTemplatedDecl());
- if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(DP))
- return ActOnStartOfFunctionDef(FnBodyScope, Function);
- return 0;
+ return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
- // FIXME: "make check" is clean if the call to dropAttrs() is commented out.
D->dropAttrs();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
FD->setInlineSpecified(false);
+
+ for (FunctionDecl::param_iterator I = FD->param_begin(),
+ E = FD->param_end();
+ I != E; ++I)
+ (*I)->dropAttrs();
}
}
@@ -5803,7 +5814,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
// In C++98/03 mode, we only give an extension warning here, because it
// is not harmful to try to explicitly instantiate something that
// has been explicitly specialized.
- Diag(NewLoc, getLangOpts().CPlusPlus0x ?
+ Diag(NewLoc, getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_explicit_instantiation_after_specialization :
diag::ext_explicit_instantiation_after_specialization)
<< PrevDecl;
@@ -5925,6 +5936,26 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
Ovl->getDeclContext()->getRedeclContext()))
continue;
+ // When matching a constexpr member function template specialization
+ // against the primary template, we don't yet know whether the
+ // specialization has an implicit 'const' (because we don't know whether
+ // it will be a static member function until we know which template it
+ // specializes), so adjust it now assuming it specializes this template.
+ QualType FT = FD->getType();
+ if (FD->isConstexpr()) {
+ CXXMethodDecl *OldMD =
+ dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ if (OldMD && OldMD->isConst()) {
+ const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.TypeQuals |= Qualifiers::Const;
+ FT = Context.getFunctionType(FPT->getResultType(),
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI);
+ }
+ }
+
// C++ [temp.expl.spec]p11:
// A trailing template-argument can be left unspecified in the
// template-id naming an explicit function template specialization
@@ -5935,10 +5966,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
TemplateDeductionInfo Info(FD->getLocation());
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult TDK
- = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs,
- FD->getType(),
- Specialization,
- Info)) {
+ = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT,
+ Specialization, Info)) {
// FIXME: Template argument deduction failed; record why it failed, so
// that we can provide nifty diagnostics.
(void)TDK;
@@ -6028,8 +6057,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
TemplArgs, /*InsertPos=*/0,
SpecInfo->getTemplateSpecializationKind(),
ExplicitTemplateArgs);
- FD->setStorageClass(Specialization->getStorageClass());
-
+
// The "previous declaration" for this function template specialization is
// the prior function template specialization.
Previous.clear();
@@ -6257,19 +6285,19 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) {
if (WasQualifiedName)
S.Diag(InstLoc,
- S.getLangOpts().CPlusPlus0x?
+ S.getLangOpts().CPlusPlus11?
diag::err_explicit_instantiation_out_of_scope :
diag::warn_explicit_instantiation_out_of_scope_0x)
<< D << NS;
else
S.Diag(InstLoc,
- S.getLangOpts().CPlusPlus0x?
+ S.getLangOpts().CPlusPlus11?
diag::err_explicit_instantiation_unqualified_wrong_namespace :
diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
<< D << NS;
} else
S.Diag(InstLoc,
- S.getLangOpts().CPlusPlus0x?
+ S.getLangOpts().CPlusPlus11?
diag::err_explicit_instantiation_must_be_global :
diag::warn_explicit_instantiation_must_be_global_0x)
<< D;
@@ -6663,7 +6691,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// well.
if (D.getDeclSpec().isInlineSpecified())
Diag(D.getDeclSpec().getInlineSpecLoc(),
- getLangOpts().CPlusPlus0x ?
+ getLangOpts().CPlusPlus11 ?
diag::err_explicit_instantiation_inline :
diag::warn_explicit_instantiation_inline_0x)
<< FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
@@ -6920,7 +6948,7 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TypenameLoc,
- getLangOpts().CPlusPlus0x ?
+ getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_typename_outside_of_template :
diag::ext_typename_outside_of_template)
<< FixItHint::CreateRemoval(TypenameLoc);
@@ -6933,15 +6961,15 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
- DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+ DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(QualifierLoc);
TL.setNameLoc(IdLoc);
} else {
- ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
+ ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>();
TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(QualifierLoc);
- cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc);
+ TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc);
}
return CreateParsedType(T, TSI);
@@ -6959,7 +6987,7 @@ Sema::ActOnTypenameType(Scope *S,
SourceLocation RAngleLoc) {
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TypenameLoc,
- getLangOpts().CPlusPlus0x ?
+ getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_typename_outside_of_template :
diag::ext_typename_outside_of_template)
<< FixItHint::CreateRemoval(TypenameLoc);
@@ -7031,12 +7059,12 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
if (!NNS || !NNS.getNestedNameSpecifier()->getAsType())
return false;
TypeLoc EnableIfTy = NNS.getTypeLoc();
- TemplateSpecializationTypeLoc *EnableIfTSTLoc =
- dyn_cast<TemplateSpecializationTypeLoc>(&EnableIfTy);
- if (!EnableIfTSTLoc || EnableIfTSTLoc->getNumArgs() == 0)
+ TemplateSpecializationTypeLoc EnableIfTSTLoc =
+ EnableIfTy.getAs<TemplateSpecializationTypeLoc>();
+ if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0)
return false;
const TemplateSpecializationType *EnableIfTST =
- cast<TemplateSpecializationType>(EnableIfTSTLoc->getTypePtr());
+ cast<TemplateSpecializationType>(EnableIfTSTLoc.getTypePtr());
// ... which names a complete class template declaration...
const TemplateDecl *EnableIfDecl =
@@ -7051,7 +7079,7 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
return false;
// Assume the first template argument is the condition.
- CondRange = EnableIfTSTLoc->getArgLoc(0).getSourceRange();
+ CondRange = EnableIfTSTLoc.getArgLoc(0).getSourceRange();
return true;
}
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index bf4533d6998c..f3bbe8a0f10c 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -10,18 +10,18 @@
//
//===----------------------------------------------------------------------===/
-#include "clang/Sema/Sema.h"
-#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "TreeTransform.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/Template.h"
#include "llvm/ADT/SmallBitVector.h"
-#include "TreeTransform.h"
#include <algorithm>
namespace clang {
@@ -130,8 +130,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgument *Params, unsigned NumParams,
const TemplateArgument *Args, unsigned NumArgs,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- bool NumberOfArgumentsMustMatch = true);
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced);
/// \brief If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
@@ -482,21 +481,26 @@ DeduceTemplateArguments(Sema &S,
return DeduceTemplateArguments(S, TemplateParams,
Param->getArgs(), Param->getNumArgs(),
SpecArg->getArgs(), SpecArg->getNumArgs(),
- Info, Deduced,
- /*NumberOfArgumentsMustMatch=*/false);
+ Info, Deduced);
}
// If the argument type is a class template specialization, we
// perform template argument deduction using its template
// arguments.
const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
- if (!RecordArg)
+ if (!RecordArg) {
+ Info.FirstArg = TemplateArgument(QualType(Param, 0));
+ Info.SecondArg = TemplateArgument(Arg);
return Sema::TDK_NonDeducedMismatch;
+ }
ClassTemplateSpecializationDecl *SpecArg
= dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
- if (!SpecArg)
+ if (!SpecArg) {
+ Info.FirstArg = TemplateArgument(QualType(Param, 0));
+ Info.SecondArg = TemplateArgument(Arg);
return Sema::TDK_NonDeducedMismatch;
+ }
// Perform template argument deduction for the template name.
if (Sema::TemplateDeductionResult Result
@@ -710,7 +714,7 @@ DeduceTemplateArguments(Sema &S,
if (NumParams != NumArgs &&
!(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
!(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1])))
- return Sema::TDK_NonDeducedMismatch;
+ return Sema::TDK_MiscellaneousDeductionFailure;
// C++0x [temp.deduct.type]p10:
// Similarly, if P has a form that contains (T), then each parameter type
@@ -727,14 +731,14 @@ DeduceTemplateArguments(Sema &S,
// Make sure we have an argument.
if (ArgIdx >= NumArgs)
- return Sema::TDK_NonDeducedMismatch;
+ return Sema::TDK_MiscellaneousDeductionFailure;
if (isa<PackExpansionType>(Args[ArgIdx])) {
// C++0x [temp.deduct.type]p22:
// If the original function parameter associated with A is a function
// parameter pack and the function parameter associated with P is not
// a function parameter pack, then template argument deduction fails.
- return Sema::TDK_NonDeducedMismatch;
+ return Sema::TDK_MiscellaneousDeductionFailure;
}
if (Sema::TemplateDeductionResult Result
@@ -827,7 +831,7 @@ DeduceTemplateArguments(Sema &S,
// Make sure we don't have any extra arguments.
if (ArgIdx < NumArgs)
- return Sema::TDK_NonDeducedMismatch;
+ return Sema::TDK_MiscellaneousDeductionFailure;
return Sema::TDK_Success;
}
@@ -1749,8 +1753,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgument *Params, unsigned NumParams,
const TemplateArgument *Args, unsigned NumArgs,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- bool NumberOfArgumentsMustMatch) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
// C++0x [temp.deduct.type]p9:
// If the template argument list of P contains a pack expansion that is not
// the last template argument, the entire template argument list is a
@@ -1770,13 +1773,12 @@ DeduceTemplateArguments(Sema &S,
// Check whether we have enough arguments.
if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
- return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch
- : Sema::TDK_Success;
+ return Sema::TDK_Success;
if (Args[ArgIdx].isPackExpansion()) {
// FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,
// but applied to pack expansions that are template arguments.
- return Sema::TDK_NonDeducedMismatch;
+ return Sema::TDK_MiscellaneousDeductionFailure;
}
// Perform deduction for this Pi/Ai pair.
@@ -1867,11 +1869,6 @@ DeduceTemplateArguments(Sema &S,
return Result;
}
- // If there is an argument remaining, then we had too many arguments.
- if (NumberOfArgumentsMustMatch &&
- hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
- return Sema::TDK_NonDeducedMismatch;
-
return Sema::TDK_Success;
}
@@ -2400,7 +2397,7 @@ Sema::SubstituteExplicitTemplateArguments(
}
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
- getLangOpts().CPlusPlus0x);
+ getLangOpts().CPlusPlus11);
ResultType = SubstType(Proto->getResultType(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
@@ -2420,15 +2417,10 @@ Sema::SubstituteExplicitTemplateArguments(
return TDK_SubstitutionFailure;
if (FunctionType) {
- *FunctionType = BuildFunctionType(ResultType,
- ParamTypes.data(), ParamTypes.size(),
- Proto->isVariadic(),
- Proto->hasTrailingReturn(),
- Proto->getTypeQuals(),
- Proto->getRefQualifier(),
+ *FunctionType = BuildFunctionType(ResultType, ParamTypes,
Function->getLocation(),
Function->getDeclName(),
- Proto->getExtInfo());
+ Proto->getExtProtoInfo());
if (FunctionType->isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
}
@@ -2656,11 +2648,15 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
if (CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
&NumExplicitArgs)
- == Param)
+ == Param) {
Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
- else
- Builder.push_back(TemplateArgument::getEmptyPack());
+ // Forget the partially-substituted pack; it's substitution is now
+ // complete.
+ CurrentInstantiationScope->ResetPartiallySubstitutedPack();
+ } else {
+ Builder.push_back(TemplateArgument::getEmptyPack());
+ }
continue;
}
@@ -2884,7 +2880,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
/// described in C++ [temp.deduct.call].
///
/// \returns true if the caller should not attempt to perform any template
-/// argument deduction based on this P/A pair.
+/// argument deduction based on this P/A pair because the argument is an
+/// overloaded function set that could not be resolved.
static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
TemplateParameterList *TemplateParams,
QualType &ParamType,
@@ -2900,7 +2897,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
if (ParamRefType) {
QualType PointeeType = ParamRefType->getPointeeType();
- // If the argument has incomplete array type, try to complete it's type.
+ // If the argument has incomplete array type, try to complete its type.
if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
ArgType = Arg->getType();
@@ -2998,8 +2995,8 @@ static bool hasDeducibleTemplateParameters(Sema &S,
/// \brief Perform template argument deduction by matching a parameter type
/// against a single expression, where the expression is an element of
-/// an initializer list that was originally matched against the argument
-/// type.
+/// an initializer list that was originally matched against a parameter
+/// of type \c initializer_list\<ParamType\>.
static Sema::TemplateDeductionResult
DeduceTemplateArgumentByListElement(Sema &S,
TemplateParameterList *TemplateParams,
@@ -3028,8 +3025,10 @@ DeduceTemplateArgumentByListElement(Sema &S,
// For all other cases, just match by type.
QualType ArgType = Arg->getType();
if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType,
- ArgType, Arg, TDF))
+ ArgType, Arg, TDF)) {
+ Info.Expression = Arg;
return Sema::TDK_FailedOverloadResolution;
+ }
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
ArgType, Info, Deduced, TDF);
}
@@ -3045,11 +3044,6 @@ DeduceTemplateArgumentByListElement(Sema &S,
///
/// \param Args the function call arguments
///
-/// \param Name the name of the function being called. This is only significant
-/// when the function template is a conversion function template, in which
-/// case this routine will also perform template argument deduction based on
-/// the function to which
-///
/// \param Specialization if template argument deduction was successful,
/// this will be set to the function template specialization produced by
/// template argument deduction.
@@ -3372,7 +3366,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// specialization, template argument deduction fails.
if (!ArgFunctionType.isNull() &&
!Context.hasSameType(ArgFunctionType, Specialization->getType()))
- return TDK_NonDeducedMismatch;
+ return TDK_MiscellaneousDeductionFailure;
return TDK_Success;
}
@@ -3772,15 +3766,15 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// first argument of the free function, which seems to match
// existing practice.
SmallVector<QualType, 4> Args1;
- unsigned Skip1 = !S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1;
- if (S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2)
+ unsigned Skip1 = !S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1;
+ if (S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2)
AddImplicitObjectParameterType(S.Context, Method1, Args1);
Args1.insert(Args1.end(),
Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
SmallVector<QualType, 4> Args2;
- Skip2 = !S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2;
- if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1)
+ Skip2 = !S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2;
+ if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1)
AddImplicitObjectParameterType(S.Context, Method2, Args2);
Args2.insert(Args2.end(),
Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
@@ -3849,7 +3843,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
unsigned NumParams = std::min(NumCallArguments,
std::min(Proto1->getNumArgs(),
Proto2->getNumArgs()));
- if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
+ if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !IsNonStatic1)
::MarkUsedTemplateParameters(S.Context, Method2->getThisType(S.Context),
false,
TemplateParams->getDepth(), UsedParameters);
@@ -4052,10 +4046,6 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
/// in this diagnostic should be unbound, which will correspond to the string
/// describing the template arguments for the function template specialization.
///
-/// \param Index if non-NULL and the result of this function is non-nULL,
-/// receives the index corresponding to the resulting function template
-/// specialization.
-///
/// \returns the most specialized function template specialization, if
/// found. Otherwise, returns SpecEnd.
///
@@ -4618,7 +4608,7 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
/// call to the given function template.
void
Sema::MarkDeducedTemplateParameters(ASTContext &Ctx,
- FunctionTemplateDecl *FunctionTemplate,
+ const FunctionTemplateDecl *FunctionTemplate,
llvm::SmallBitVector &Deduced) {
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 665dd07b8f85..f755b8ca452d 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -12,16 +12,16 @@
#include "clang/Sema/SemaInternal.h"
#include "TreeTransform.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/Basic/LangOptions.h"
using namespace clang;
using namespace sema;
@@ -182,7 +182,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ActiveTemplateInstantiation Inst;
Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+ Inst.Entity = Entity;
Inst.TemplateArgs = 0;
Inst.NumTemplateArgs = 0;
Inst.InstantiationRange = InstantiationRange;
@@ -205,7 +205,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ActiveTemplateInstantiation Inst;
Inst.Kind = ActiveTemplateInstantiation::ExceptionSpecInstantiation;
Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+ Inst.Entity = Entity;
Inst.TemplateArgs = 0;
Inst.NumTemplateArgs = 0;
Inst.InstantiationRange = InstantiationRange;
@@ -230,7 +230,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Inst.Kind
= ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = reinterpret_cast<uintptr_t>(Template);
+ Inst.Entity = Template;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.InstantiationRange = InstantiationRange;
@@ -255,7 +255,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ActiveTemplateInstantiation Inst;
Inst.Kind = Kind;
Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
+ Inst.Entity = FunctionTemplate;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.DeductionInfo = &DeductionInfo;
@@ -283,7 +283,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ActiveTemplateInstantiation Inst;
Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
+ Inst.Entity = PartialSpec;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.DeductionInfo = &DeductionInfo;
@@ -308,7 +308,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Inst.Kind
= ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.Entity = Param;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.InstantiationRange = InstantiationRange;
@@ -332,7 +332,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Template = Template;
- Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.Entity = Param;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.InstantiationRange = InstantiationRange;
@@ -356,7 +356,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Template = Template;
- Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.Entity = Param;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.InstantiationRange = InstantiationRange;
@@ -380,7 +380,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Template = Template;
- Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.Entity = Param;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.InstantiationRange = InstantiationRange;
@@ -454,7 +454,7 @@ void Sema::PrintInstantiationStack() {
switch (Active->Kind) {
case ActiveTemplateInstantiation::TemplateInstantiation: {
- Decl *D = reinterpret_cast<Decl *>(Active->Entity);
+ Decl *D = Active->Entity;
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
unsigned DiagID = diag::note_template_member_class_here;
if (isa<ClassTemplateSpecializationDecl>(Record))
@@ -491,22 +491,23 @@ void Sema::PrintInstantiationStack() {
}
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
- TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
- std::string TemplateArgsStr
- = TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateDecl *Template = cast<TemplateDecl>(Active->Entity);
+ SmallVector<char, 128> TemplateArgsStr;
+ llvm::raw_svector_ostream OS(TemplateArgsStr);
+ Template->printName(OS);
+ TemplateSpecializationType::PrintTemplateArgumentList(OS,
Active->TemplateArgs,
Active->NumTemplateArgs,
getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation,
diag::note_default_arg_instantiation_here)
- << (Template->getNameAsString() + TemplateArgsStr)
+ << OS.str()
<< Active->InstantiationRange;
break;
}
case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
- FunctionTemplateDecl *FnTmpl
- = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+ FunctionTemplateDecl *FnTmpl = cast<FunctionTemplateDecl>(Active->Entity);
Diags.Report(Active->PointOfInstantiation,
diag::note_explicit_template_arg_substitution_here)
<< FnTmpl
@@ -518,9 +519,8 @@ void Sema::PrintInstantiationStack() {
}
case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
- if (ClassTemplatePartialSpecializationDecl *PartialSpec
- = dyn_cast<ClassTemplatePartialSpecializationDecl>(
- (Decl *)Active->Entity)) {
+ if (ClassTemplatePartialSpecializationDecl *PartialSpec =
+ dyn_cast<ClassTemplatePartialSpecializationDecl>(Active->Entity)) {
Diags.Report(Active->PointOfInstantiation,
diag::note_partial_spec_deduct_instantiation_here)
<< Context.getTypeDeclType(PartialSpec)
@@ -531,7 +531,7 @@ void Sema::PrintInstantiationStack() {
<< Active->InstantiationRange;
} else {
FunctionTemplateDecl *FnTmpl
- = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+ = cast<FunctionTemplateDecl>(Active->Entity);
Diags.Report(Active->PointOfInstantiation,
diag::note_function_template_deduction_instantiation_here)
<< FnTmpl
@@ -543,23 +543,25 @@ void Sema::PrintInstantiationStack() {
break;
case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: {
- ParmVarDecl *Param = cast<ParmVarDecl>((Decl *)Active->Entity);
+ ParmVarDecl *Param = cast<ParmVarDecl>(Active->Entity);
FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
- std::string TemplateArgsStr
- = TemplateSpecializationType::PrintTemplateArgumentList(
+ SmallVector<char, 128> TemplateArgsStr;
+ llvm::raw_svector_ostream OS(TemplateArgsStr);
+ FD->printName(OS);
+ TemplateSpecializationType::PrintTemplateArgumentList(OS,
Active->TemplateArgs,
Active->NumTemplateArgs,
getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation,
diag::note_default_function_arg_instantiation_here)
- << (FD->getNameAsString() + TemplateArgsStr)
+ << OS.str()
<< Active->InstantiationRange;
break;
}
case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: {
- NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity);
+ NamedDecl *Parm = cast<NamedDecl>(Active->Entity);
std::string Name;
if (!Parm->getName().empty())
Name = std::string(" '") + Parm->getName().str() + "'";
@@ -603,16 +605,16 @@ void Sema::PrintInstantiationStack() {
case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
Diags.Report(Active->PointOfInstantiation,
diag::note_template_exception_spec_instantiation_here)
- << cast<FunctionDecl>((Decl *)Active->Entity)
+ << cast<FunctionDecl>(Active->Entity)
<< Active->InstantiationRange;
break;
}
}
}
-llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
+Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
if (InNonInstantiationSFINAEContext)
- return llvm::Optional<TemplateDeductionInfo *>(0);
+ return Optional<TemplateDeductionInfo *>(0);
for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
Active = ActiveTemplateInstantiations.rbegin(),
@@ -624,13 +626,13 @@ llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case ActiveTemplateInstantiation::TemplateInstantiation:
// An instantiation of an alias template may or may not be a SFINAE
// context, depending on what else is on the stack.
- if (isa<TypeAliasTemplateDecl>(reinterpret_cast<Decl *>(Active->Entity)))
+ if (isa<TypeAliasTemplateDecl>(Active->Entity))
break;
// Fall through.
case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
// This is a template instantiation, so there is no SFINAE.
- return llvm::Optional<TemplateDeductionInfo *>();
+ return None;
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
@@ -649,7 +651,7 @@ llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
}
}
- return llvm::Optional<TemplateDeductionInfo *>();
+ return None;
}
/// \brief Retrieve the depth and index of a parameter pack.
@@ -709,7 +711,7 @@ namespace {
llvm::ArrayRef<UnexpandedParameterPack> Unexpanded,
bool &ShouldExpand,
bool &RetainExpansion,
- llvm::Optional<unsigned> &NumExpansions) {
+ Optional<unsigned> &NumExpansions) {
return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
PatternRange, Unexpanded,
TemplateArgs,
@@ -829,7 +831,7 @@ namespace {
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
- llvm::Optional<unsigned> NumExpansions,
+ Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
/// \brief Transforms a template type parameter type by performing
@@ -1267,7 +1269,7 @@ TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
// Transform each of the parameter expansions into the corresponding
// parameters in the instantiation of the function decl.
- llvm::SmallVector<Decl*, 8> Parms;
+ SmallVector<Decl *, 8> Parms;
Parms.reserve(E->getNumExpansions());
for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
I != End; ++I) {
@@ -1365,7 +1367,7 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
ParmVarDecl *
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
- llvm::Optional<unsigned> NumExpansions,
+ Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
NumExpansions, ExpectParameterPack);
@@ -1568,10 +1570,10 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
return true;
TypeLoc TL = T->getTypeLoc().IgnoreParens();
- if (!isa<FunctionProtoTypeLoc>(TL))
+ if (!TL.getAs<FunctionProtoTypeLoc>())
return false;
- FunctionProtoTypeLoc FP = cast<FunctionProtoTypeLoc>(TL);
+ FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>();
for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) {
ParmVarDecl *P = FP.getArg(I);
@@ -1615,9 +1617,9 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
TLB.reserve(TL.getFullDataSize());
QualType Result;
-
- if (FunctionProtoTypeLoc *Proto = dyn_cast<FunctionProtoTypeLoc>(&TL)) {
- Result = Instantiator.TransformFunctionProtoType(TLB, *Proto, ThisContext,
+
+ if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
+ Result = Instantiator.TransformFunctionProtoType(TLB, Proto, ThisContext,
ThisTypeQuals);
} else {
Result = Instantiator.TransformType(TLB, TL);
@@ -1631,15 +1633,14 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,
- llvm::Optional<unsigned> NumExpansions,
+ Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
TypeSourceInfo *NewDI = 0;
TypeLoc OldTL = OldDI->getTypeLoc();
- if (isa<PackExpansionTypeLoc>(OldTL)) {
- PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(OldTL);
-
+ if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) {
+
// We have a function parameter pack. Substitute into the pattern of the
// expansion.
NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
@@ -1681,8 +1682,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
OldParm->getLocation(),
OldParm->getIdentifier(),
NewDI->getType(), NewDI,
- OldParm->getStorageClass(),
- OldParm->getStorageClassAsWritten());
+ OldParm->getStorageClass());
if (!NewParm)
return 0;
@@ -1715,7 +1715,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
OldParm->getFunctionScopeIndex() + indexAdjustment);
-
+
+ InstantiateAttrs(TemplateArgs, OldParm, NewParm);
+
return NewParm;
}
@@ -1767,7 +1769,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions;
+ Optional<unsigned> NumExpansions;
if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(),
Base->getSourceRange(),
Unexpanded,
@@ -2047,6 +2049,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CheckCompletedCXXClass(Instantiation);
// Attach any in-class member initializers now the class is complete.
+ // FIXME: We are supposed to defer instantiating these until they are needed.
if (!FieldsWithMemberInitializers.empty()) {
// C++11 [expr.prim.general]p4:
// Otherwise, if a member-declarator declares a non-static data member
@@ -2583,12 +2586,21 @@ Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
return Instantiator.TransformExpr(E);
}
+ExprResult Sema::SubstInitializer(Expr *Init,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool CXXDirectInit) {
+ TemplateInstantiator Instantiator(*this, TemplateArgs,
+ SourceLocation(),
+ DeclarationName());
+ return Instantiator.TransformInitializer(Init, CXXDirectInit);
+}
+
bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
const MultiLevelTemplateArgumentList &TemplateArgs,
SmallVectorImpl<Expr *> &Outputs) {
if (NumExprs == 0)
return false;
-
+
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
DeclarationName());
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 19c46ab9c97f..33e83d07d634 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -10,9 +10,6 @@
//
//===----------------------------------------------------------------------===/
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/PrettyDeclStackTrace.h"
-#include "clang/Sema/Template.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
@@ -22,6 +19,9 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Template.h"
using namespace clang;
@@ -60,6 +60,64 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
// Include attribute instantiation code.
#include "clang/Sema/AttrTemplateInstantiate.inc"
+static void instantiateDependentAlignedAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const AlignedAttr *Aligned, Decl *New, bool IsPackExpansion) {
+ if (Aligned->isAlignmentExpr()) {
+ // The alignment expression is a constant expression.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated);
+ ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs);
+ if (!Result.isInvalid())
+ S.AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(),
+ Aligned->getSpellingListIndex(), IsPackExpansion);
+ } else {
+ TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(),
+ TemplateArgs, Aligned->getLocation(),
+ DeclarationName());
+ if (Result)
+ S.AddAlignedAttr(Aligned->getLocation(), New, Result,
+ Aligned->getSpellingListIndex(), IsPackExpansion);
+ }
+}
+
+static void instantiateDependentAlignedAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const AlignedAttr *Aligned, Decl *New) {
+ if (!Aligned->isPackExpansion()) {
+ instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false);
+ return;
+ }
+
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ if (Aligned->isAlignmentExpr())
+ S.collectUnexpandedParameterPacks(Aligned->getAlignmentExpr(),
+ Unexpanded);
+ else
+ S.collectUnexpandedParameterPacks(Aligned->getAlignmentType()->getTypeLoc(),
+ Unexpanded);
+ assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+
+ // Determine whether we can expand this attribute pack yet.
+ bool Expand = true, RetainExpansion = false;
+ Optional<unsigned> NumExpansions;
+ // FIXME: Use the actual location of the ellipsis.
+ SourceLocation EllipsisLoc = Aligned->getLocation();
+ if (S.CheckParameterPacksForExpansion(EllipsisLoc, Aligned->getRange(),
+ Unexpanded, TemplateArgs, Expand,
+ RetainExpansion, NumExpansions))
+ return;
+
+ if (!Expand) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, -1);
+ instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, true);
+ } else {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I);
+ instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false);
+ }
+ }
+}
+
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New,
LateInstantiatedAttrVec *LateAttrs,
@@ -69,31 +127,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Attr *TmplAttr = *i;
// FIXME: This should be generalized to more than just the AlignedAttr.
- if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
- if (Aligned->isAlignmentDependent()) {
- if (Aligned->isAlignmentExpr()) {
- // The alignment expression is a constant expression.
- EnterExpressionEvaluationContext Unevaluated(*this,
- Sema::ConstantEvaluated);
-
- ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
- TemplateArgs);
- if (!Result.isInvalid())
- AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(),
- Aligned->getIsMSDeclSpec());
- } else {
- TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
- TemplateArgs,
- Aligned->getLocation(),
- DeclarationName());
- if (Result)
- AddAlignedAttr(Aligned->getLocation(), New, Result,
- Aligned->getIsMSDeclSpec());
- }
- continue;
- }
+ const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr);
+ if (Aligned && Aligned->isAlignmentDependent()) {
+ instantiateDependentAlignedAttr(*this, TemplateArgs, Aligned, New);
+ continue;
}
+ assert(!TmplAttr->isPackExpansion());
if (TmplAttr->isLateParsed() && LateAttrs) {
// Late parsed attributes must be instantiated and attached after the
// enclosing class has been instantiated. See Sema::InstantiateClass.
@@ -189,9 +229,9 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
// tag decl, re-establish that relationship for the new typedef.
if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) {
TagDecl *oldTag = oldTagType->getDecl();
- if (oldTag->getTypedefNameForAnonDecl() == D) {
+ if (oldTag->getTypedefNameForAnonDecl() == D && !Invalid) {
TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl();
- assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl());
+ assert(!newTag->hasNameForLinkage());
newTag->setTypedefNameForAnonDecl(Typedef);
}
}
@@ -245,8 +285,8 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
TypeAliasTemplateDecl *PrevAliasTemplate = 0;
if (Pattern->getPreviousDecl()) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
- if (Found.first != Found.second) {
- PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first);
+ if (!Found.empty()) {
+ PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Found.front());
}
}
@@ -298,8 +338,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
D->getInnerLocStart(),
D->getLocation(), D->getIdentifier(),
DI->getType(), DI,
- D->getStorageClass(),
- D->getStorageClassAsWritten());
+ D->getStorageClass());
Var->setThreadSpecified(D->isThreadSpecified());
Var->setInitStyle(D->getInitStyle());
Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
@@ -322,6 +361,11 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
Var->setReferenced(D->isReferenced());
}
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope);
+
+ if (Var->hasAttrs())
+ SemaRef.CheckAlignasUnderalignment(Var);
+
// FIXME: In theory, we could have a previous declaration for variables that
// are not static data members.
// FIXME: having to fake up a LookupResult is dumb.
@@ -345,7 +389,6 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
if (Owner->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
}
- SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope);
// Link instantiations of static data members back to the template from
// which they were instantiated.
@@ -459,6 +502,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope);
+ if (Field->hasAttrs())
+ SemaRef.CheckAlignasUnderalignment(Field);
+
if (Invalid)
Field->setInvalidDecl();
@@ -745,8 +791,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (!isFriend && Pattern->getPreviousDecl()) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
- if (Found.first != Found.second) {
- PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first);
+ if (!Found.empty()) {
+ PrevClassTemplate = dyn_cast<ClassTemplateDecl>(Found.front());
if (PrevClassTemplate)
PrevDecl = PrevClassTemplate->getTemplatedDecl();
}
@@ -911,11 +957,11 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
// of the class template and return that.
DeclContext::lookup_result Found
= Owner->lookup(ClassTemplate->getDeclName());
- if (Found.first == Found.second)
+ if (Found.empty())
return 0;
ClassTemplateDecl *InstClassTemplate
- = dyn_cast<ClassTemplateDecl>(*Found.first);
+ = dyn_cast<ClassTemplateDecl>(Found.front());
if (!InstClassTemplate)
return 0;
@@ -1043,8 +1089,8 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context,
FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo();
NewEPI.ExtInfo = OrigFunc->getExtInfo();
return Context.getFunctionType(NewFunc->getResultType(),
- NewFunc->arg_type_begin(),
- NewFunc->getNumArgs(),
+ ArrayRef<QualType>(NewFunc->arg_type_begin(),
+ NewFunc->getNumArgs()),
NewEPI);
}
@@ -1116,10 +1162,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
FunctionDecl *Function =
FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
D->getNameInfo(), T, TInfo,
- D->getStorageClass(), D->getStorageClassAsWritten(),
+ D->getStorageClass(),
D->isInlineSpecified(), D->hasWrittenPrototype(),
D->isConstexpr());
+ if (D->isInlined())
+ Function->setImplicitlyInline();
+
if (QualifierLoc)
Function->setQualifierInfo(QualifierLoc);
@@ -1287,7 +1336,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
//
// If -Wc++98-compat is enabled, we go through the motions of checking for a
// redefinition, but don't instantiate the function.
- if ((!SemaRef.getLangOpts().CPlusPlus0x ||
+ if ((!SemaRef.getLangOpts().CPlusPlus11 ||
SemaRef.Diags.getDiagnosticLevel(
diag::warn_cxx98_compat_friend_redefinition,
Function->getLocation())
@@ -1298,11 +1347,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
if (Function->isDefined(Definition) &&
Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
SemaRef.Diag(Function->getLocation(),
- SemaRef.getLangOpts().CPlusPlus0x ?
+ SemaRef.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_friend_redefinition :
diag::err_redefinition) << Function->getDeclName();
SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
- if (!SemaRef.getLangOpts().CPlusPlus0x)
+ if (!SemaRef.getLangOpts().CPlusPlus11)
Function->setInvalidDecl();
}
// Check for redefinitions due to other instantiations of this or
@@ -1314,7 +1363,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
continue;
switch (R->getFriendObjectKind()) {
case Decl::FOK_None:
- if (!SemaRef.getLangOpts().CPlusPlus0x &&
+ if (!SemaRef.getLangOpts().CPlusPlus11 &&
!queuedInstantiation && R->isUsed(false)) {
if (MemberSpecializationInfo *MSInfo
= Function->getMemberSpecializationInfo()) {
@@ -1333,12 +1382,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
= R->getTemplateInstantiationPattern())
if (RPattern->isDefined(RPattern)) {
SemaRef.Diag(Function->getLocation(),
- SemaRef.getLangOpts().CPlusPlus0x ?
+ SemaRef.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_friend_redefinition :
diag::err_redefinition)
<< Function->getDeclName();
SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
- if (!SemaRef.getLangOpts().CPlusPlus0x)
+ if (!SemaRef.getLangOpts().CPlusPlus11)
Function->setInvalidDecl();
break;
}
@@ -1479,12 +1528,14 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
} else {
Method = CXXMethodDecl::Create(SemaRef.Context, Record,
StartLoc, NameInfo, T, TInfo,
- D->isStatic(),
- D->getStorageClassAsWritten(),
+ D->getStorageClass(),
D->isInlineSpecified(),
D->isConstexpr(), D->getLocEnd());
}
+ if (D->isInlined())
+ Method->setImplicitlyInline();
+
if (QualifierLoc)
Method->setQualifierInfo(QualifierLoc);
@@ -1581,10 +1632,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
SemaRef.CheckOverrideControl(Method);
// If a function is defined as defaulted or deleted, mark it as such now.
- if (D->isDefaulted())
- Method->setDefaulted();
+ if (D->isExplicitlyDefaulted())
+ SemaRef.SetDeclDefaulted(Method, Method->getLocation());
if (D->isDeletedAsWritten())
- Method->setDeletedAsWritten();
+ SemaRef.SetDeclDeleted(Method, Method->getLocation());
// If there's a function template, let our caller handle it.
if (FunctionTemplate) {
@@ -1610,13 +1661,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Owner->addDecl(Method);
}
- if (D->isExplicitlyDefaulted()) {
- SemaRef.SetDeclDefaulted(Method, Method->getLocation());
- } else {
- assert(!D->isDefaulted() &&
- "should not implicitly default uninstantiated function");
- }
-
return Method;
}
@@ -1633,9 +1677,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
}
ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
- return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0,
- llvm::Optional<unsigned>(),
- /*ExpectParameterPack=*/false);
+ return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, None,
+ /*ExpectParameterPack=*/ false);
}
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
@@ -1701,7 +1744,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
// The non-type template parameter pack's type is a pack expansion of types.
// Determine whether we need to expand this parameter pack into separate
// types.
- PackExpansionTypeLoc Expansion = cast<PackExpansionTypeLoc>(TL);
+ PackExpansionTypeLoc Expansion = TL.castAs<PackExpansionTypeLoc>();
TypeLoc Pattern = Expansion.getPatternLoc();
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
@@ -1710,9 +1753,9 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
- llvm::Optional<unsigned> OrigNumExpansions
+ Optional<unsigned> OrigNumExpansions
= Expansion.getTypePtr()->getNumExpansions();
- llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+ Optional<unsigned> NumExpansions = OrigNumExpansions;
if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(),
Pattern.getSourceRange(),
Unexpanded,
@@ -1867,7 +1910,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions;
+ Optional<unsigned> NumExpansions;
if (SemaRef.CheckParameterPacksForExpansion(D->getLocation(),
TempParams->getSourceRange(),
Unexpanded,
@@ -2069,7 +2112,7 @@ Decl * TemplateDeclInstantiator
SS.Adopt(QualifierLoc);
// Since NameInfo refers to a typename, it cannot be a C++ special name.
- // Hence, no tranformation is required for it.
+ // Hence, no transformation is required for it.
DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
NamedDecl *UD =
SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
@@ -2138,6 +2181,23 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
return NewFD;
}
+Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
+ OMPThreadPrivateDecl *D) {
+ SmallVector<DeclRefExpr *, 5> Vars;
+ for (ArrayRef<DeclRefExpr *>::iterator I = D->varlist_begin(),
+ E = D->varlist_end();
+ I != E; ++I) {
+ Expr *Var = SemaRef.SubstExpr(*I, TemplateArgs).take();
+ assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr");
+ Vars.push_back(cast<DeclRefExpr>(Var));
+ }
+
+ OMPThreadPrivateDecl *TD =
+ SemaRef.CheckOMPThreadPrivateDecl(D->getLocation(), Vars);
+
+ return TD;
+}
+
Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
@@ -2330,18 +2390,17 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
if (NewTInfo != OldTInfo) {
// Get parameters from the new type info.
TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
- if (FunctionProtoTypeLoc *OldProtoLoc
- = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) {
+ if (FunctionProtoTypeLoc OldProtoLoc =
+ OldTL.getAs<FunctionProtoTypeLoc>()) {
TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens();
- FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL);
- assert(NewProtoLoc && "Missing prototype?");
+ FunctionProtoTypeLoc NewProtoLoc = NewTL.castAs<FunctionProtoTypeLoc>();
unsigned NewIdx = 0;
- for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs();
+ for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumArgs();
OldIdx != NumOldParams; ++OldIdx) {
- ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx);
+ ParmVarDecl *OldParam = OldProtoLoc.getArg(OldIdx);
LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope;
- llvm::Optional<unsigned> NumArgumentsInExpansion;
+ Optional<unsigned> NumArgumentsInExpansion;
if (OldParam->isParameterPack())
NumArgumentsInExpansion =
SemaRef.getNumArgumentsInExpansion(OldParam->getType(),
@@ -2349,14 +2408,14 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
if (!NumArgumentsInExpansion) {
// Simple case: normal parameter, or a parameter pack that's
// instantiated to a (still-dependent) parameter pack.
- ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
+ ParmVarDecl *NewParam = NewProtoLoc.getArg(NewIdx++);
Params.push_back(NewParam);
Scope->InstantiatedLocal(OldParam, NewParam);
} else {
// Parameter pack expansion: make the instantiation an argument pack.
Scope->MakeInstantiatedLocalArgPack(OldParam);
for (unsigned I = 0; I != *NumArgumentsInExpansion; ++I) {
- ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
+ ParmVarDecl *NewParam = NewProtoLoc.getArg(NewIdx++);
Params.push_back(NewParam);
Scope->InstantiatedLocalPackArg(OldParam, NewParam);
}
@@ -2368,10 +2427,10 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
// substitution occurred. However, we still need to instantiate
// the function parameters themselves.
TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
- if (FunctionProtoTypeLoc *OldProtoLoc
- = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) {
- for (unsigned i = 0, i_end = OldProtoLoc->getNumArgs(); i != i_end; ++i) {
- ParmVarDecl *Parm = VisitParmVarDecl(OldProtoLoc->getArg(i));
+ if (FunctionProtoTypeLoc OldProtoLoc =
+ OldTL.getAs<FunctionProtoTypeLoc>()) {
+ for (unsigned i = 0, i_end = OldProtoLoc.getNumArgs(); i != i_end; ++i) {
+ ParmVarDecl *Parm = VisitParmVarDecl(OldProtoLoc.getArg(i));
if (!Parm)
return 0;
Params.push_back(Parm);
@@ -2403,7 +2462,7 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
// Expand the parameter pack.
Scope.MakeInstantiatedLocalArgPack(PatternParam);
- llvm::Optional<unsigned> NumArgumentsInExpansion
+ Optional<unsigned> NumArgumentsInExpansion
= S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
assert(NumArgumentsInExpansion &&
"should only be called when all template arguments are known");
@@ -2434,7 +2493,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
ThisTypeQuals = Method->getTypeQualifiers();
}
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
- SemaRef.getLangOpts().CPlusPlus0x);
+ SemaRef.getLangOpts().CPlusPlus11);
// The function has an exception specification or a "noreturn"
// attribute. Substitute into each of the exception types.
@@ -2452,7 +2511,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
bool Expand = false;
bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions
+ Optional<unsigned> NumExpansions
= PackExpansion->getNumExpansions();
if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
SourceRange(),
@@ -2541,8 +2600,8 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
EPI.NoexceptExpr = NoexceptExpr;
New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
- NewProto->arg_type_begin(),
- NewProto->getNumArgs(),
+ ArrayRef<QualType>(NewProto->arg_type_begin(),
+ NewProto->getNumArgs()),
EPI));
}
@@ -2560,8 +2619,8 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.ExceptionSpecType = EST_None;
Decl->setType(Context.getFunctionType(Proto->getResultType(),
- Proto->arg_type_begin(),
- Proto->getNumArgs(),
+ ArrayRef<QualType>(Proto->arg_type_begin(),
+ Proto->getNumArgs()),
EPI));
return;
}
@@ -2605,12 +2664,12 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
if (FunctionTemplateDecl *FunTmpl
- = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) {
+ = dyn_cast<FunctionTemplateDecl>(ActiveInst.Entity)) {
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
"Deduction from the wrong function template?");
(void) FunTmpl;
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
- ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+ ActiveInst.Entity = New;
}
}
@@ -2622,7 +2681,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// DR1330: In C++11, defer instantiation of a non-trivial
// exception specification.
- if (SemaRef.getLangOpts().CPlusPlus0x &&
+ if (SemaRef.getLangOpts().CPlusPlus11 &&
EPI.ExceptionSpecType != EST_None &&
EPI.ExceptionSpecType != EST_DynamicNone &&
EPI.ExceptionSpecType != EST_BasicNoexcept) {
@@ -2641,8 +2700,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
EPI.ExceptionSpecDecl = New;
EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
- NewProto->arg_type_begin(),
- NewProto->getNumArgs(),
+ ArrayRef<QualType>(NewProto->arg_type_begin(),
+ NewProto->getNumArgs()),
EPI));
} else {
::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
@@ -2770,6 +2829,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
!PatternDecl->isInlined())
return;
+ if (PatternDecl->isInlined())
+ Function->setImplicitlyInline();
+
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
if (Inst)
return;
@@ -2789,7 +2851,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
EnterExpressionEvaluationContext EvalContext(*this,
Sema::PotentiallyEvaluated);
- ActOnStartOfFunctionDef(0, Function);
// Introduce a new scope where local variable instantiations will be
// recorded, unless we're actually a member function within a local
@@ -2801,21 +2862,21 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
LocalInstantiationScope Scope(*this, MergeWithParentScope);
- // Enter the scope of this instantiation. We don't use
- // PushDeclContext because we don't have a scope.
- Sema::ContextRAII savedContext(*this, Function);
+ if (PatternDecl->isDefaulted())
+ SetDeclDefaulted(Function, PatternDecl->getLocation());
+ else {
+ ActOnStartOfFunctionDef(0, Function);
- MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ Sema::ContextRAII savedContext(*this, Function);
- addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
- TemplateArgs);
+ MultiLevelTemplateArgumentList TemplateArgs =
+ getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
- if (PatternDecl->isDefaulted()) {
- ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
+ addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
+ TemplateArgs);
- SetDeclDefaulted(Function, PatternDecl->getLocation());
- } else {
// If this is a constructor, instantiate the member initializers.
if (const CXXConstructorDecl *Ctor =
dyn_cast<CXXConstructorDecl>(PatternDecl)) {
@@ -2831,11 +2892,11 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
ActOnFinishFunctionBody(Function, Body.get(),
/*IsInstantiation=*/true);
- }
- PerformDependentDiagnostics(PatternDecl, TemplateArgs);
+ PerformDependentDiagnostics(PatternDecl, TemplateArgs);
- savedContext.pop();
+ savedContext.pop();
+ }
DeclGroupRef DG(Function);
Consumer.HandleTopLevelDecl(DG);
@@ -2928,7 +2989,18 @@ void Sema::InstantiateStaticDataMemberDefinition(
if (TSK == TSK_ExplicitInstantiationDeclaration)
return;
- Consumer.HandleCXXStaticMemberVarInstantiation(Var);
+ // Make sure to pass the instantiated variable to the consumer at the end.
+ struct PassToConsumerRAII {
+ ASTConsumer &Consumer;
+ VarDecl *Var;
+
+ PassToConsumerRAII(ASTConsumer &Consumer, VarDecl *Var)
+ : Consumer(Consumer), Var(Var) { }
+
+ ~PassToConsumerRAII() {
+ Consumer.HandleCXXStaticMemberVarInstantiation(Var);
+ }
+ } PassToConsumerRAII(Consumer, Var);
// If we already have a definition, we're done.
if (VarDecl *Def = Var->getDefinition()) {
@@ -2965,12 +3037,11 @@ void Sema::InstantiateStaticDataMemberDefinition(
previousContext.pop();
if (Var) {
+ PassToConsumerRAII.Var = Var;
MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
assert(MSInfo && "Missing member specialization information?");
Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation());
- DeclGroupRef DG(Var);
- Consumer.HandleTopLevelDecl(DG);
}
Local.Exit();
@@ -3024,7 +3095,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
collectUnexpandedParameterPacks(BaseTL, Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions;
+ Optional<unsigned> NumExpansions;
if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(),
BaseTL.getSourceRange(),
Unexpanded,
@@ -3142,49 +3213,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
ActOnMemInitializers(New,
/*FIXME: ColonLoc */
SourceLocation(),
- NewInits.data(), NewInits.size(),
+ NewInits,
AnyErrors);
}
-ExprResult Sema::SubstInitializer(Expr *Init,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- bool CXXDirectInit) {
- // Initializers are instantiated like expressions, except that various outer
- // layers are stripped.
- if (!Init)
- return Owned(Init);
-
- if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
- Init = ExprTemp->getSubExpr();
-
- while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
- Init = Binder->getSubExpr();
-
- if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
- Init = ICE->getSubExprAsWritten();
-
- // If this is a direct-initializer, we take apart CXXConstructExprs.
- // Everything else is passed through.
- CXXConstructExpr *Construct;
- if (!CXXDirectInit || !(Construct = dyn_cast<CXXConstructExpr>(Init)) ||
- isa<CXXTemporaryObjectExpr>(Construct))
- return SubstExpr(Init, TemplateArgs);
-
- SmallVector<Expr*, 8> NewArgs;
- if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true,
- TemplateArgs, NewArgs))
- return ExprError();
-
- // Treat an empty initializer like none.
- if (NewArgs.empty())
- return Owned((Expr*)0);
-
- // Build a ParenListExpr to represent anything else.
- // FIXME: Fake locations!
- SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart());
- return ActOnParenListExpr(Loc, Loc, NewArgs);
-}
-
// TODO: this could be templated if the various decl types used the
// same method name.
static bool isInstantiationOf(ClassTemplateDecl *Pattern,
@@ -3539,7 +3571,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
NamedDecl *Result = 0;
if (D->getDeclName()) {
DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
- Result = findInstantiationOf(Context, D, Found.first, Found.second);
+ Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
} else {
// Since we don't have a name for the entity we're looking for,
// our only option is to walk through all of the declarations to
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 6147d63ef44b..c0ad2be6d40e 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -10,14 +10,14 @@
//===----------------------------------------------------------------------===/
#include "clang/Sema/Sema.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/AST/TypeLoc.h"
using namespace clang;
@@ -443,17 +443,16 @@ TypeResult Sema::ActOnPackExpansion(ParsedType Type,
if (!TSInfo)
return true;
- TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc,
- llvm::Optional<unsigned>());
+ TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc, None);
if (!TSResult)
return true;
return CreateParsedType(TSResult->getType(), TSResult);
}
-TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
- SourceLocation EllipsisLoc,
- llvm::Optional<unsigned> NumExpansions) {
+TypeSourceInfo *
+Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc,
+ Optional<unsigned> NumExpansions) {
// Create the pack expansion type and source-location information.
QualType Result = CheckPackExpansion(Pattern->getType(),
Pattern->getTypeLoc().getSourceRange(),
@@ -462,7 +461,8 @@ TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
return 0;
TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
- PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
+ PackExpansionTypeLoc TL =
+ TSResult->getTypeLoc().castAs<PackExpansionTypeLoc>();
TL.setEllipsisLoc(EllipsisLoc);
// Copy over the source-location information from the type.
@@ -472,10 +472,9 @@ TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
return TSResult;
}
-QualType Sema::CheckPackExpansion(QualType Pattern,
- SourceRange PatternRange,
+QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
SourceLocation EllipsisLoc,
- llvm::Optional<unsigned> NumExpansions) {
+ Optional<unsigned> NumExpansions) {
// C++0x [temp.variadic]p5:
// The pattern of a pack expansion shall name one or more
// parameter packs that are not expanded by a nested pack
@@ -490,11 +489,11 @@ QualType Sema::CheckPackExpansion(QualType Pattern,
}
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
- return CheckPackExpansion(Pattern, EllipsisLoc, llvm::Optional<unsigned>());
+ return CheckPackExpansion(Pattern, EllipsisLoc, None);
}
ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
- llvm::Optional<unsigned> NumExpansions) {
+ Optional<unsigned> NumExpansions) {
if (!Pattern)
return ExprError();
@@ -526,13 +525,11 @@ getDepthAndIndex(NamedDecl *ND) {
return std::make_pair(TTP->getDepth(), TTP->getIndex());
}
-bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
- SourceRange PatternRange,
- ArrayRef<UnexpandedParameterPack> Unexpanded,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- bool &ShouldExpand,
- bool &RetainExpansion,
- llvm::Optional<unsigned> &NumExpansions) {
+bool Sema::CheckParameterPacksForExpansion(
+ SourceLocation EllipsisLoc, SourceRange PatternRange,
+ ArrayRef<UnexpandedParameterPack> Unexpanded,
+ const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand,
+ bool &RetainExpansion, Optional<unsigned> &NumExpansions) {
ShouldExpand = true;
RetainExpansion = false;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
@@ -636,13 +633,13 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
return false;
}
-llvm::Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T,
+Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T,
const MultiLevelTemplateArgumentList &TemplateArgs) {
QualType Pattern = cast<PackExpansionType>(T)->getPattern();
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
- llvm::Optional<unsigned> Result;
+ Optional<unsigned> Result;
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
// Compute the depth and index for this parameter pack.
unsigned Depth;
@@ -664,7 +661,7 @@ llvm::Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T,
if (Instantiation->is<Decl*>())
// The pattern refers to an unexpanded pack. We're not ready to expand
// this pack yet.
- return llvm::Optional<unsigned>();
+ return None;
unsigned Size = Instantiation->get<DeclArgumentPack *>()->size();
assert((!Result || *Result == Size) && "inconsistent pack sizes");
@@ -678,7 +675,7 @@ llvm::Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T,
!TemplateArgs.hasTemplateArgument(Depth, Index))
// The pattern refers to an unknown template argument. We're not ready to
// expand this pack yet.
- return llvm::Optional<unsigned>();
+ return None;
// Determine the size of the argument pack.
unsigned Size = TemplateArgs(Depth, Index).pack_size();
@@ -731,6 +728,14 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_class:
case TST_auto:
case TST_unknown_anytype:
+ case TST_image1d_t:
+ case TST_image1d_array_t:
+ case TST_image1d_buffer_t:
+ case TST_image2d_t:
+ case TST_image2d_array_t:
+ case TST_image3d_t:
+ case TST_sampler_t:
+ case TST_event_t:
case TST_error:
break;
}
@@ -837,7 +842,7 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
return ExprError();
}
- MarkAnyDeclReferenced(OpLoc, ParameterPack);
+ MarkAnyDeclReferenced(OpLoc, ParameterPack, true);
return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc,
ParameterPack, NameLoc, RParenLoc);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 4b23167951aa..7169eeab9b93 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -11,18 +11,16 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Template.h"
-#include "clang/Basic/OpenCL.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
-#include "clang/AST/Expr.h"
+#include "clang/Basic/OpenCL.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -30,7 +28,10 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Template.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -106,7 +107,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
case AttributeList::AT_Pascal: \
case AttributeList::AT_Regparm: \
case AttributeList::AT_Pcs: \
- case AttributeList::AT_PnaclCall \
+ case AttributeList::AT_PnaclCall: \
+ case AttributeList::AT_IntelOclBicc \
namespace {
/// An object which stores processing state for the entire
@@ -149,6 +151,10 @@ namespace {
return declarator;
}
+ bool isProcessingDeclSpec() const {
+ return chunkIndex == declarator.getNumTypeObjects();
+ }
+
unsigned getCurrentChunkIndex() const {
return chunkIndex;
}
@@ -159,8 +165,7 @@ namespace {
}
AttributeList *&getCurrentAttrListRef() const {
- assert(chunkIndex <= declarator.getNumTypeObjects());
- if (chunkIndex == declarator.getNumTypeObjects())
+ if (isProcessingDeclSpec())
return getMutableDeclSpec().getAttributes().getListRef();
return declarator.getTypeObject(chunkIndex).getAttrListRef();
}
@@ -269,8 +274,18 @@ static void moveAttrFromListToList(AttributeList &attr,
spliceAttrIntoList(attr, toList);
}
+/// The location of a type attribute.
+enum TypeAttrLocation {
+ /// The attribute is in the decl-specifier-seq.
+ TAL_DeclSpec,
+ /// The attribute is part of a DeclaratorChunk.
+ TAL_DeclChunk,
+ /// The attribute is immediately after the declaration's name.
+ TAL_DeclName
+};
+
static void processTypeAttrs(TypeProcessingState &state,
- QualType &type, bool isDeclSpec,
+ QualType &type, TypeAttrLocation TAL,
AttributeList *attrs);
static bool handleFunctionTypeAttr(TypeProcessingState &state,
@@ -291,6 +306,66 @@ static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
return handleObjCOwnershipTypeAttr(state, attr, type);
}
+/// Given the index of a declarator chunk, check whether that chunk
+/// directly specifies the return type of a function and, if so, find
+/// an appropriate place for it.
+///
+/// \param i - a notional index which the search will start
+/// immediately inside
+static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
+ unsigned i) {
+ assert(i <= declarator.getNumTypeObjects());
+
+ DeclaratorChunk *result = 0;
+
+ // First, look inwards past parens for a function declarator.
+ for (; i != 0; --i) {
+ DeclaratorChunk &fnChunk = declarator.getTypeObject(i-1);
+ switch (fnChunk.Kind) {
+ case DeclaratorChunk::Paren:
+ continue;
+
+ // If we find anything except a function, bail out.
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::MemberPointer:
+ return result;
+
+ // If we do find a function declarator, scan inwards from that,
+ // looking for a block-pointer declarator.
+ case DeclaratorChunk::Function:
+ for (--i; i != 0; --i) {
+ DeclaratorChunk &blockChunk = declarator.getTypeObject(i-1);
+ switch (blockChunk.Kind) {
+ case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::MemberPointer:
+ continue;
+ case DeclaratorChunk::BlockPointer:
+ result = &blockChunk;
+ goto continue_outer;
+ }
+ llvm_unreachable("bad declarator chunk kind");
+ }
+
+ // If we run out of declarators doing that, we're done.
+ return result;
+ }
+ llvm_unreachable("bad declarator chunk kind");
+
+ // Okay, reconsider from our new point.
+ continue_outer: ;
+ }
+
+ // Ran out of chunks, bail out.
+ return result;
+}
+
/// Given that an objc_gc attribute was written somewhere on a
/// declaration *other* than on the declarator itself (for which, use
/// distributeObjCPointerTypeAttrFromDeclarator), and given that it
@@ -300,22 +375,44 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType type) {
Declarator &declarator = state.getDeclarator();
+
+ // Move it to the outermost normal or block pointer declarator.
for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
switch (chunk.Kind) {
case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::BlockPointer: {
+ // But don't move an ARC ownership attribute to the return type
+ // of a block.
+ DeclaratorChunk *destChunk = 0;
+ if (state.isProcessingDeclSpec() &&
+ attr.getKind() == AttributeList::AT_ObjCOwnership)
+ destChunk = maybeMovePastReturnType(declarator, i - 1);
+ if (!destChunk) destChunk = &chunk;
+
moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
+ destChunk->getAttrListRef());
return;
+ }
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
continue;
+ // We may be starting at the return type of a block.
+ case DeclaratorChunk::Function:
+ if (state.isProcessingDeclSpec() &&
+ attr.getKind() == AttributeList::AT_ObjCOwnership) {
+ if (DeclaratorChunk *dest = maybeMovePastReturnType(declarator, i)) {
+ moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+ dest->getAttrListRef());
+ return;
+ }
+ }
+ goto error;
+
// Don't walk through these.
case DeclaratorChunk::Reference:
- case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
goto error;
}
@@ -452,6 +549,15 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
QualType &declSpecType) {
state.saveDeclSpecAttrs();
+ // C++11 attributes before the decl specifiers actually appertain to
+ // the declarators. Move them straight there. We don't support the
+ // 'put them wherever you like' semantics we allow for GNU attributes.
+ if (attr.isCXX11Attribute()) {
+ moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+ state.getDeclarator().getAttrListRef());
+ return;
+ }
+
// Try to distribute to the innermost.
if (distributeFunctionTypeAttrToInnermost(state, attr,
state.getCurrentAttrListRef(),
@@ -501,6 +607,11 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
do {
next = attr->getNext();
+ // Do not distribute C++11 attributes. They have strict rules for what
+ // they appertain to.
+ if (attr->isCXX11Attribute())
+ continue;
+
switch (attr->getKind()) {
OBJC_POINTER_TYPE_ATTRS_CASELIST:
distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
@@ -712,7 +823,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
if (!S.getLangOpts().C99) {
if (S.getLangOpts().CPlusPlus)
S.Diag(DS.getTypeSpecWidthLoc(),
- S.getLangOpts().CPlusPlus0x ?
+ S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
else
S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong);
@@ -731,7 +842,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
if (!S.getLangOpts().C99) {
if (S.getLangOpts().CPlusPlus)
S.Diag(DS.getTypeSpecWidthLoc(),
- S.getLangOpts().CPlusPlus0x ?
+ S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
else
S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong);
@@ -742,6 +853,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
}
case DeclSpec::TST_int128:
+ if (!S.PP.getTargetInfo().hasInt128Type())
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported);
if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
Result = Context.UnsignedInt128Ty;
else
@@ -901,6 +1014,38 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
+ case DeclSpec::TST_image1d_t:
+ Result = Context.OCLImage1dTy;
+ break;
+
+ case DeclSpec::TST_image1d_array_t:
+ Result = Context.OCLImage1dArrayTy;
+ break;
+
+ case DeclSpec::TST_image1d_buffer_t:
+ Result = Context.OCLImage1dBufferTy;
+ break;
+
+ case DeclSpec::TST_image2d_t:
+ Result = Context.OCLImage2dTy;
+ break;
+
+ case DeclSpec::TST_image2d_array_t:
+ Result = Context.OCLImage2dArrayTy;
+ break;
+
+ case DeclSpec::TST_image3d_t:
+ Result = Context.OCLImage3dTy;
+ break;
+
+ case DeclSpec::TST_sampler_t:
+ Result = Context.OCLSamplerTy;
+ break;
+
+ case DeclSpec::TST_event_t:
+ Result = Context.OCLEventTy;
+ break;
+
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -936,57 +1081,27 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// list of type attributes to be temporarily saved while the type
// attributes are pushed around.
if (AttributeList *attrs = DS.getAttributes().getList())
- processTypeAttrs(state, Result, true, attrs);
+ processTypeAttrs(state, Result, TAL_DeclSpec, attrs);
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
- // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
- // or incomplete types shall not be restrict-qualified." C++ also allows
- // restrict-qualified references.
- if (TypeQuals & DeclSpec::TQ_restrict) {
- if (Result->isAnyPointerType() || Result->isReferenceType()) {
- QualType EltTy;
- if (Result->isObjCObjectPointerType())
- EltTy = Result;
- else
- EltTy = Result->isPointerType() ?
- Result->getAs<PointerType>()->getPointeeType() :
- Result->getAs<ReferenceType>()->getPointeeType();
-
- // If we have a pointer or reference, the pointee must have an object
- // incomplete type.
- if (!EltTy->isIncompleteOrObjectType()) {
- S.Diag(DS.getRestrictSpecLoc(),
- diag::err_typecheck_invalid_restrict_invalid_pointee)
- << EltTy << DS.getSourceRange();
- TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
- }
- } else {
- S.Diag(DS.getRestrictSpecLoc(),
- diag::err_typecheck_invalid_restrict_not_pointer)
- << Result << DS.getSourceRange();
- TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
- }
- }
-
// Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
// of a function type includes any type qualifiers, the behavior is
// undefined."
if (Result->isFunctionType() && TypeQuals) {
- // Get some location to point at, either the C or V location.
- SourceLocation Loc;
if (TypeQuals & DeclSpec::TQ_const)
- Loc = DS.getConstSpecLoc();
+ S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers)
+ << Result << DS.getSourceRange();
else if (TypeQuals & DeclSpec::TQ_volatile)
- Loc = DS.getVolatileSpecLoc();
+ S.Diag(DS.getVolatileSpecLoc(), diag::warn_typecheck_function_qualifiers)
+ << Result << DS.getSourceRange();
else {
- assert((TypeQuals & DeclSpec::TQ_restrict) &&
- "Has CVR quals but not C, V, or R?");
- Loc = DS.getRestrictSpecLoc();
+ assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) &&
+ "Has CVRA quals but not C, V, R, or A?");
+ // No diagnostic; we'll diagnose 'restrict' or '_Atomic' applied to a
+ // function type later, in BuildQualifiedType.
}
- S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
- << Result << DS.getSourceRange();
}
// C++ [dcl.ref]p1:
@@ -999,6 +1114,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
TypeQuals && Result->isReferenceType()) {
TypeQuals &= ~DeclSpec::TQ_const;
TypeQuals &= ~DeclSpec::TQ_volatile;
+ TypeQuals &= ~DeclSpec::TQ_atomic;
}
// C90 6.5.3 constraints: "The same type qualifier shall not appear more
@@ -1016,12 +1132,17 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
<< "volatile";
}
- // C90 doesn't have restrict, so it doesn't force us to produce a warning
- // in this case.
+ // C90 doesn't have restrict nor _Atomic, so it doesn't force us to
+ // produce a warning in this case.
}
- Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
- Result = Context.getQualifiedType(Result, Quals);
+ QualType Qualified = S.BuildQualifiedType(Result, DeclLoc, TypeQuals, &DS);
+
+ // If adding qualifiers fails, just use the unqualified type.
+ if (Qualified.isNull())
+ declarator.setInvalidType(true);
+ else
+ Result = Qualified;
}
return Result;
@@ -1035,37 +1156,36 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) {
}
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
- Qualifiers Qs) {
+ Qualifiers Qs, const DeclSpec *DS) {
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
if (Qs.hasRestrict()) {
unsigned DiagID = 0;
QualType ProblemTy;
- const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
- if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) {
- if (!RTy->getPointeeType()->isIncompleteOrObjectType()) {
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<ReferenceType>()->getPointeeType();
- }
- } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
- if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<PointerType>()->getPointeeType();
- }
- } else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) {
- if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
+ if (T->isAnyPointerType() || T->isReferenceType() ||
+ T->isMemberPointerType()) {
+ QualType EltTy;
+ if (T->isObjCObjectPointerType())
+ EltTy = T;
+ else if (const MemberPointerType *PTy = T->getAs<MemberPointerType>())
+ EltTy = PTy->getPointeeType();
+ else
+ EltTy = T->getPointeeType();
+
+ // If we have a pointer or reference, the pointee must have an object
+ // incomplete type.
+ if (!EltTy->isIncompleteOrObjectType()) {
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<PointerType>()->getPointeeType();
+ ProblemTy = EltTy;
}
- } else if (!Ty->isDependentType()) {
- // FIXME: this deserves a proper diagnostic
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ } else if (!T->isDependentType()) {
+ DiagID = diag::err_typecheck_invalid_restrict_not_pointer;
ProblemTy = T;
}
if (DiagID) {
- Diag(Loc, DiagID) << ProblemTy;
+ Diag(DS ? DS->getRestrictSpecLoc() : Loc, DiagID) << ProblemTy;
Qs.removeRestrict();
}
}
@@ -1073,6 +1193,39 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
return Context.getQualifiedType(T, Qs);
}
+QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
+ unsigned CVRA, const DeclSpec *DS) {
+ // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic.
+ unsigned CVR = CVRA & ~DeclSpec::TQ_atomic;
+
+ // C11 6.7.3/5:
+ // If the same qualifier appears more than once in the same
+ // specifier-qualifier-list, either directly or via one or more typedefs,
+ // the behavior is the same as if it appeared only once.
+ //
+ // It's not specified what happens when the _Atomic qualifier is applied to
+ // a type specified with the _Atomic specifier, but we assume that this
+ // should be treated as if the _Atomic qualifier appeared multiple times.
+ if (CVRA & DeclSpec::TQ_atomic && !T->isAtomicType()) {
+ // C11 6.7.3/5:
+ // If other qualifiers appear along with the _Atomic qualifier in a
+ // specifier-qualifier-list, the resulting type is the so-qualified
+ // atomic type.
+ //
+ // Don't need to worry about array types here, since _Atomic can't be
+ // applied to such types.
+ SplitQualType Split = T.getSplitUnqualifiedType();
+ T = BuildAtomicType(QualType(Split.Ty, 0),
+ DS ? DS->getAtomicSpecLoc() : Loc);
+ if (T.isNull())
+ return T;
+ Split.Quals.addCVRQualifiers(CVR);
+ return BuildQualifiedType(T, Loc, Split.Quals);
+ }
+
+ return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR), DS);
+}
+
/// \brief Build a paren type including \p T.
QualType Sema::BuildParenType(QualType T) {
return Context.getParenType(T);
@@ -1338,7 +1491,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
// C99 6.7.5.2p1: The size expression shall have integer type.
// C++11 allows contextual conversions to such types.
- if (!getLangOpts().CPlusPlus0x &&
+ if (!getLangOpts().CPlusPlus11 &&
ArraySize && !ArraySize->isTypeDependent() &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
@@ -1359,7 +1512,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
isArraySizeVLA(*this, ArraySize, ConstVal)) {
// Even in C++11, don't allow contextual conversions in the array bound
// of a VLA.
- if (getLangOpts().CPlusPlus0x &&
+ if (getLangOpts().CPlusPlus11 &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
<< ArraySize->getType() << ArraySize->getSourceRange();
@@ -1409,6 +1562,12 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
+
+ // OpenCL v1.2 s6.9.d: variable length arrays are not supported.
+ if (getLangOpts().OpenCL && T->isVariableArrayType()) {
+ Diag(Loc, diag::err_opencl_vla);
+ return QualType();
+ }
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
@@ -1435,6 +1594,11 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
: diag::ext_c99_array_usage) << ASM;
}
+ if (T->isVariableArrayType()) {
+ // Warn about VLAs for -Wvla.
+ Diag(Loc, diag::warn_vla_used);
+ }
+
return T;
}
@@ -1475,45 +1639,10 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
}
-/// \brief Build a function type.
-///
-/// This routine checks the function type according to C++ rules and
-/// under the assumption that the result type and parameter types have
-/// just been instantiated from a template. It therefore duplicates
-/// some of the behavior of GetTypeForDeclarator, but in a much
-/// simpler form that is only suitable for this narrow use case.
-///
-/// \param T The return type of the function.
-///
-/// \param ParamTypes The parameter types of the function. This array
-/// will be modified to account for adjustments to the types of the
-/// function parameters.
-///
-/// \param NumParamTypes The number of parameter types in ParamTypes.
-///
-/// \param Variadic Whether this is a variadic function type.
-///
-/// \param HasTrailingReturn Whether this function has a trailing return type.
-///
-/// \param Quals The cvr-qualifiers to be applied to the function type.
-///
-/// \param Loc The location of the entity whose type involves this
-/// function type or, if there is no such entity, the location of the
-/// type that will have function type.
-///
-/// \param Entity The name of the entity that involves the function
-/// type, if known.
-///
-/// \returns A suitable function type, if there are no
-/// errors. Otherwise, returns a NULL type.
QualType Sema::BuildFunctionType(QualType T,
- QualType *ParamTypes,
- unsigned NumParamTypes,
- bool Variadic, bool HasTrailingReturn,
- unsigned Quals,
- RefQualifierKind RefQualifier,
+ llvm::MutableArrayRef<QualType> ParamTypes,
SourceLocation Loc, DeclarationName Entity,
- FunctionType::ExtInfo Info) {
+ const FunctionProtoType::ExtProtoInfo &EPI) {
if (T->isArrayType() || T->isFunctionType()) {
Diag(Loc, diag::err_func_returning_array_function)
<< T->isFunctionType() << T;
@@ -1528,7 +1657,7 @@ QualType Sema::BuildFunctionType(QualType T,
}
bool Invalid = false;
- for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
+ for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) {
// FIXME: Loc is too inprecise here, should use proper locations for args.
QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
if (ParamType->isVoidType()) {
@@ -1547,14 +1676,7 @@ QualType Sema::BuildFunctionType(QualType T,
if (Invalid)
return QualType();
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.Variadic = Variadic;
- EPI.HasTrailingReturn = HasTrailingReturn;
- EPI.TypeQuals = Quals;
- EPI.RefQualifier = RefQualifier;
- EPI.ExtInfo = Info;
-
- return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI);
+ return Context.getFunctionType(T, ParamTypes, EPI);
}
/// \brief Build a member pointer type \c T Class::*.
@@ -1601,13 +1723,33 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return QualType();
}
- // In the Microsoft ABI, the class is allowed to be an incomplete
- // type. In such cases, the compiler makes a worst-case assumption.
- // We make no such assumption right now, so emit an error if the
- // class isn't a complete type.
- if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
- RequireCompleteType(Loc, Class, diag::err_incomplete_type))
- return QualType();
+ // C++ allows the class type in a member pointer to be an incomplete type.
+ // In the Microsoft ABI, the size of the member pointer can vary
+ // according to the class type, which means that we really need a
+ // complete type if possible, which means we need to instantiate templates.
+ //
+ // If template instantiation fails or the type is just incomplete, we have to
+ // add an extra slot to the member pointer. Yes, this does cause problems
+ // when passing pointers between TUs that disagree about the size.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ CXXRecordDecl *RD = Class->getAsCXXRecordDecl();
+ if (RD && !RD->hasAttr<MSInheritanceAttr>()) {
+ // Lock in the inheritance model on the first use of a member pointer.
+ // Otherwise we may disagree about the size at different points in the TU.
+ // FIXME: MSVC picks a model on the first use that needs to know the size,
+ // rather than on the first mention of the type, e.g. typedefs.
+ if (RequireCompleteType(Loc, Class, 0) && !RD->isBeingDefined()) {
+ // We know it doesn't have an attribute and it's incomplete, so use the
+ // unspecified inheritance model. If we're in the record body, we can
+ // figure out the inheritance model.
+ for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
+ E = RD->redecls_end(); I != E; ++I) {
+ I->addAttr(::new (Context) UnspecifiedInheritanceAttr(
+ RD->getSourceRange(), Context));
+ }
+ }
+ }
+ }
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -1754,50 +1896,118 @@ static void inferARCWriteback(TypeProcessingState &state,
// TODO: mark whether we did this inference?
}
-static void DiagnoseIgnoredQualifiers(unsigned Quals,
- SourceLocation ConstQualLoc,
- SourceLocation VolatileQualLoc,
- SourceLocation RestrictQualLoc,
- Sema& S) {
- std::string QualStr;
+static void diagnoseIgnoredQualifiers(
+ Sema &S, unsigned Quals,
+ SourceLocation FallbackLoc,
+ SourceLocation ConstQualLoc = SourceLocation(),
+ SourceLocation VolatileQualLoc = SourceLocation(),
+ SourceLocation RestrictQualLoc = SourceLocation(),
+ SourceLocation AtomicQualLoc = SourceLocation()) {
+ if (!Quals)
+ return;
+
+ const SourceManager &SM = S.getSourceManager();
+
+ struct Qual {
+ unsigned Mask;
+ const char *Name;
+ 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 }
+ };
+
+ llvm::SmallString<32> QualStr;
unsigned NumQuals = 0;
SourceLocation Loc;
+ FixItHint FixIts[4];
+
+ // Build a string naming the redundant qualifiers.
+ for (unsigned I = 0; I != 4; ++I) {
+ if (Quals & QualKinds[I].Mask) {
+ if (!QualStr.empty()) QualStr += ' ';
+ QualStr += QualKinds[I].Name;
+
+ // If we have a location for the qualifier, offer a fixit.
+ SourceLocation QualLoc = QualKinds[I].Loc;
+ if (!QualLoc.isInvalid()) {
+ FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc);
+ if (Loc.isInvalid() || SM.isBeforeInTranslationUnit(QualLoc, Loc))
+ Loc = QualLoc;
+ }
- FixItHint ConstFixIt;
- FixItHint VolatileFixIt;
- FixItHint RestrictFixIt;
+ ++NumQuals;
+ }
+ }
- const SourceManager &SM = S.getSourceManager();
+ S.Diag(Loc.isInvalid() ? FallbackLoc : Loc, diag::warn_qual_return_type)
+ << QualStr << NumQuals << FixIts[0] << FixIts[1] << FixIts[2] << FixIts[3];
+}
+
+// Diagnose pointless type qualifiers on the return type of a function.
+static void diagnoseIgnoredFunctionQualifiers(Sema &S, QualType RetTy,
+ Declarator &D,
+ unsigned FunctionChunkIndex) {
+ if (D.getTypeObject(FunctionChunkIndex).Fun.hasTrailingReturnType()) {
+ // FIXME: TypeSourceInfo doesn't preserve location information for
+ // qualifiers.
+ diagnoseIgnoredQualifiers(S, RetTy.getLocalCVRQualifiers(),
+ D.getIdentifierLoc());
+ return;
+ }
+
+ for (unsigned OuterChunkIndex = FunctionChunkIndex + 1,
+ End = D.getNumTypeObjects();
+ OuterChunkIndex != End; ++OuterChunkIndex) {
+ DeclaratorChunk &OuterChunk = D.getTypeObject(OuterChunkIndex);
+ switch (OuterChunk.Kind) {
+ case DeclaratorChunk::Paren:
+ continue;
+
+ case DeclaratorChunk::Pointer: {
+ DeclaratorChunk::PointerTypeInfo &PTI = OuterChunk.Ptr;
+ diagnoseIgnoredQualifiers(
+ S, PTI.TypeQuals,
+ SourceLocation(),
+ SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
+ SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
+ SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
+ SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc));
+ return;
+ }
+
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::MemberPointer:
+ // FIXME: We can't currently provide an accurate source location and a
+ // fix-it hint for these.
+ unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0;
+ diagnoseIgnoredQualifiers(S, RetTy.getCVRQualifiers() | AtomicQual,
+ D.getIdentifierLoc());
+ return;
+ }
+
+ llvm_unreachable("unknown declarator chunk kind");
+ }
+
+ // If the qualifiers come from a conversion function type, don't diagnose
+ // them -- they're not necessarily redundant, since such a conversion
+ // operator can be explicitly called as "x.operator const int()".
+ if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId)
+ return;
- // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to
- // find a range and grow it to encompass all the qualifiers, regardless of
- // the order in which they textually appear.
- if (Quals & Qualifiers::Const) {
- ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc);
- QualStr = "const";
- ++NumQuals;
- if (!Loc.isValid() || SM.isBeforeInTranslationUnit(ConstQualLoc, Loc))
- Loc = ConstQualLoc;
- }
- if (Quals & Qualifiers::Volatile) {
- VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc);
- QualStr += (NumQuals == 0 ? "volatile" : " volatile");
- ++NumQuals;
- if (!Loc.isValid() || SM.isBeforeInTranslationUnit(VolatileQualLoc, Loc))
- Loc = VolatileQualLoc;
- }
- if (Quals & Qualifiers::Restrict) {
- RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc);
- QualStr += (NumQuals == 0 ? "restrict" : " restrict");
- ++NumQuals;
- if (!Loc.isValid() || SM.isBeforeInTranslationUnit(RestrictQualLoc, Loc))
- Loc = RestrictQualLoc;
- }
-
- assert(NumQuals > 0 && "No known qualifiers?");
-
- S.Diag(Loc, diag::warn_qual_return_type)
- << QualStr << NumQuals << ConstFixIt << VolatileFixIt << RestrictFixIt;
+ // Just parens all the way out to the decl specifiers. Diagnose any qualifiers
+ // which are present there.
+ diagnoseIgnoredQualifiers(S, D.getDeclSpec().getTypeQualifiers(),
+ D.getIdentifierLoc(),
+ D.getDeclSpec().getConstSpecLoc(),
+ D.getDeclSpec().getVolatileSpecLoc(),
+ D.getDeclSpec().getRestrictSpecLoc(),
+ D.getDeclSpec().getAtomicSpecLoc());
}
static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
@@ -1832,7 +2042,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// "void" instead.
T = SemaRef.Context.VoidTy;
if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList())
- processTypeAttrs(state, T, true, attrs);
+ processTypeAttrs(state, T, TAL_DeclSpec, attrs);
break;
case UnqualifiedId::IK_ConversionFunctionId:
@@ -1851,7 +2061,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// type (this is checked later) and we can skip this. In other languages
// using auto, we need to check regardless.
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
- (!SemaRef.getLangOpts().CPlusPlus0x || !D.isFunctionDeclarator())) {
+ (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
int Error = -1;
switch (D.getContext()) {
@@ -1917,7 +2127,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// 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().CPlusPlus0x && Error != -1) {
+ if (SemaRef.getLangOpts().CPlusPlus11 && Error != -1) {
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
@@ -1969,6 +2179,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
SemaRef.Diag(OwnedTagDecl->getLocation(),
diag::err_type_defined_in_alias_template)
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+ D.setInvalidType(true);
break;
case Declarator::TypeNameContext:
case Declarator::TemplateParamContext:
@@ -1979,6 +2190,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
SemaRef.Diag(OwnedTagDecl->getLocation(),
diag::err_type_defined_in_type_specifier)
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+ D.setInvalidType(true);
break;
case Declarator::PrototypeContext:
case Declarator::ObjCParameterContext:
@@ -1989,6 +2201,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
SemaRef.Diag(OwnedTagDecl->getLocation(),
diag::err_type_defined_in_param_type)
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+ D.setInvalidType(true);
break;
case Declarator::ConditionContext:
// C++ 6.4p2:
@@ -1996,6 +2209,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// a new class or enumeration.
SemaRef.Diag(OwnedTagDecl->getLocation(),
diag::err_type_defined_in_condition);
+ D.setInvalidType(true);
break;
}
}
@@ -2087,7 +2301,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
if (!D.isFunctionDeclarator() ||
D.getFunctionDefinitionKind() != FDK_Declaration ||
!S.CurContext->isFunctionOrMethod() ||
- D.getDeclSpec().getStorageClassSpecAsWritten()
+ D.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_unspecified)
return;
@@ -2150,7 +2364,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
<< FixItHint::CreateRemoval(ParenRange);
else {
std::string Init = S.getFixItZeroInitializerForType(RT);
- if (Init.empty() && S.LangOpts.CPlusPlus0x)
+ if (Init.empty() && S.LangOpts.CPlusPlus11)
Init = "{}";
if (!Init.empty())
S.Diag(DeclType.Loc, diag::note_empty_parens_zero_initialize)
@@ -2376,38 +2590,61 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Do not allow returning half FP value.
// FIXME: This really should be in BuildFunctionType.
if (T->isHalfType()) {
- S.Diag(D.getIdentifierLoc(),
- diag::err_parameters_retval_cannot_have_fp16_type) << 1
- << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
- D.setInvalidType(true);
+ if (S.getLangOpts().OpenCL) {
+ if (!S.getOpenCLOptions().cl_khr_fp16) {
+ S.Diag(D.getIdentifierLoc(), diag::err_opencl_half_return) << T;
+ D.setInvalidType(true);
+ }
+ } else {
+ S.Diag(D.getIdentifierLoc(),
+ diag::err_parameters_retval_cannot_have_fp16_type) << 1;
+ D.setInvalidType(true);
+ }
}
// cv-qualifiers on return types are pointless except when the type is a
// class type in C++.
- if (isa<PointerType>(T) && T.getLocalCVRQualifiers() &&
- (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId) &&
- (!LangOpts.CPlusPlus || !T->isDependentType())) {
- assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?");
- DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
- assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer);
-
- DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr;
-
- DiagnoseIgnoredQualifiers(PTI.TypeQuals,
- SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
- SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
- SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
- S);
-
- } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
- (!LangOpts.CPlusPlus ||
- (!T->isDependentType() && !T->isRecordType()))) {
-
- DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(),
- D.getDeclSpec().getConstSpecLoc(),
- D.getDeclSpec().getVolatileSpecLoc(),
- D.getDeclSpec().getRestrictSpecLoc(),
- S);
+ if ((T.getCVRQualifiers() || T->isAtomicType()) &&
+ !(S.getLangOpts().CPlusPlus &&
+ (T->isDependentType() || T->isRecordType())))
+ diagnoseIgnoredFunctionQualifiers(S, T, D, chunkIndex);
+
+ // Objective-C ARC ownership qualifiers are ignored on the function
+ // return type (by type canonicalization). Complain if this attribute
+ // was written here.
+ if (T.getQualifiers().hasObjCLifetime()) {
+ SourceLocation AttrLoc;
+ if (chunkIndex + 1 < D.getNumTypeObjects()) {
+ DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
+ for (const AttributeList *Attr = ReturnTypeChunk.getAttrs();
+ Attr; Attr = Attr->getNext()) {
+ if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
+ AttrLoc = Attr->getLoc();
+ break;
+ }
+ }
+ }
+ if (AttrLoc.isInvalid()) {
+ for (const AttributeList *Attr
+ = D.getDeclSpec().getAttributes().getList();
+ Attr; Attr = Attr->getNext()) {
+ if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
+ AttrLoc = Attr->getLoc();
+ break;
+ }
+ }
+ }
+
+ if (AttrLoc.isValid()) {
+ // The ownership attributes are almost always written via
+ // the predefined
+ // __strong/__weak/__autoreleasing/__unsafe_unretained.
+ if (AttrLoc.isMacroID())
+ AttrLoc = S.SourceMgr.getImmediateExpansionRange(AttrLoc).first;
+
+ S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
+ << T.getQualifiers().getObjCLifetime();
+ }
}
if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
@@ -2457,6 +2694,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// definition.
S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
D.setInvalidType(true);
+ // Recover by creating a K&R-style function type.
+ T = Context.getFunctionNoProtoType(T);
break;
}
@@ -2514,10 +2753,18 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
} else if (ArgTy->isHalfType()) {
// Disallow half FP arguments.
// FIXME: This really should be in BuildFunctionType.
- S.Diag(Param->getLocation(),
- diag::err_parameters_retval_cannot_have_fp16_type) << 0
- << FixItHint::CreateInsertion(Param->getLocation(), "*");
- D.setInvalidType();
+ if (S.getLangOpts().OpenCL) {
+ if (!S.getOpenCLOptions().cl_khr_fp16) {
+ S.Diag(Param->getLocation(),
+ diag::err_opencl_half_argument) << ArgTy;
+ D.setInvalidType();
+ Param->setInvalidDecl();
+ }
+ } else {
+ S.Diag(Param->getLocation(),
+ diag::err_parameters_retval_cannot_have_fp16_type) << 0;
+ D.setInvalidType();
+ }
} else if (!FTI.hasPrototype) {
if (ArgTy->isPromotableIntegerType()) {
ArgTy = Context.getPromotedIntegerType(ArgTy);
@@ -2568,7 +2815,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
Exceptions,
EPI);
- T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
+ T = Context.getFunctionType(T, ArgTys, EPI);
}
break;
@@ -2634,7 +2881,7 @@ 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, false, attrs);
+ processTypeAttrs(state, T, TAL_DeclChunk, attrs);
}
if (LangOpts.CPlusPlus && T->isFunctionType()) {
@@ -2659,30 +2906,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
FreeFunction = (DC && !DC->isRecord());
}
- // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member
- // function that is not a constructor declares that function to be const.
- // FIXME: This should be deferred until we know whether this is a static
- // member function (for an out-of-class definition, we don't know
- // this until we perform redeclaration lookup).
- if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
- D.getName().getKind() != UnqualifiedId::IK_ConstructorName &&
- D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId &&
- !(FnTy->getTypeQuals() & DeclSpec::TQ_const)) {
- // Rebuild function type adding a 'const' qualifier.
- FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
- EPI.TypeQuals |= DeclSpec::TQ_const;
- T = Context.getFunctionType(FnTy->getResultType(),
- FnTy->arg_type_begin(),
- FnTy->getNumArgs(), EPI);
- // Rebuild any parens around the identifier in the function type.
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren)
- break;
- T = S.BuildParenType(T);
- }
- }
-
// C++11 [dcl.fct]p6 (w/DR1417):
// An attempt to specify a function type with a cv-qualifier-seq or a
// ref-qualifier (including by typedef-name) is ill-formed unless it is:
@@ -2732,8 +2955,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
EPI.RefQualifier = RQ_None;
T = Context.getFunctionType(FnTy->getResultType(),
- FnTy->arg_type_begin(),
- FnTy->getNumArgs(), EPI);
+ ArrayRef<QualType>(FnTy->arg_type_begin(),
+ FnTy->getNumArgs()),
+ EPI);
// Rebuild any parens around the identifier in the function type.
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren)
@@ -2746,7 +2970,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Apply any undistributed attributes from the declarator.
if (!T.isNull())
if (AttributeList *attrs = D.getAttributes())
- processTypeAttrs(state, T, false, attrs);
+ processTypeAttrs(state, T, TAL_DeclName, attrs);
// Diagnose any ignored type attributes.
if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T);
@@ -2782,7 +3006,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getSourceRange();
D.setEllipsisLoc(SourceLocation());
} else {
- T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
+ T = Context.getPackExpansionType(T, None);
}
break;
@@ -2796,10 +3020,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// parameter packs in the type of the non-type template parameter, then
// it expands those parameter packs.
if (T->containsUnexpandedParameterPack())
- T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
+ T = Context.getPackExpansionType(T, None);
else
S.Diag(D.getEllipsisLoc(),
- LangOpts.CPlusPlus0x
+ LangOpts.CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
break;
@@ -3006,6 +3230,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_Pcs;
case AttributedType::attr_pnaclcall:
return AttributeList::AT_PnaclCall;
+ case AttributedType::attr_inteloclbicc:
+ return AttributeList::AT_IntelOclBicc;
}
llvm_unreachable("unexpected attribute kind!");
}
@@ -3099,13 +3325,13 @@ namespace {
TypeLoc OldTL = TInfo->getTypeLoc();
if (TInfo->getType()->getAs<ElaboratedType>()) {
- ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(OldTL);
- TemplateSpecializationTypeLoc NamedTL =
- cast<TemplateSpecializationTypeLoc>(ElabTL.getNamedTypeLoc());
+ ElaboratedTypeLoc ElabTL = OldTL.castAs<ElaboratedTypeLoc>();
+ TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc()
+ .castAs<TemplateSpecializationTypeLoc>();
TL.copy(NamedTL);
}
else
- TL.copy(cast<TemplateSpecializationTypeLoc>(OldTL));
+ TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
@@ -3153,7 +3379,7 @@ namespace {
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
- TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc()));
+ TL.copy(TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>());
return;
}
}
@@ -3169,7 +3395,7 @@ namespace {
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
- TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc()));
+ TL.copy(TInfo->getTypeLoc().castAs<DependentNameTypeLoc>());
}
void VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
@@ -3177,19 +3403,29 @@ namespace {
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
- TL.copy(cast<DependentTemplateSpecializationTypeLoc>(
- TInfo->getTypeLoc()));
+ TL.copy(
+ TInfo->getTypeLoc().castAs<DependentTemplateSpecializationTypeLoc>());
}
void VisitTagTypeLoc(TagTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
- TL.setKWLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
+ // An AtomicTypeLoc can come from either an _Atomic(...) type specifier
+ // or an _Atomic qualifier.
+ if (DS.getTypeSpecType() == DeclSpec::TST_atomic) {
+ TL.setKWLoc(DS.getTypeSpecTypeLoc());
+ TL.setParensRange(DS.getTypeofParensRange());
- TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ assert(TInfo);
+ TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
+ } else {
+ TL.setKWLoc(DS.getAtomicSpecLoc());
+ // No parens, to indicate this was spelled as an _Atomic qualifier.
+ TL.setParensRange(SourceRange());
+ Visit(TL.getValueLoc());
+ }
}
void VisitTypeLoc(TypeLoc TL) {
@@ -3239,7 +3475,7 @@ namespace {
case NestedNameSpecifier::Identifier:
assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
{
- DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL);
+ DependentNameTypeLoc DNTLoc = ClsTL.castAs<DependentNameTypeLoc>();
DNTLoc.setElaboratedKeywordLoc(SourceLocation());
DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
@@ -3249,7 +3485,7 @@ namespace {
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
if (isa<ElaboratedType>(ClsTy)) {
- ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL);
+ ElaboratedTypeLoc ETLoc = ClsTL.castAs<ElaboratedTypeLoc>();
ETLoc.setElaboratedKeywordLoc(SourceLocation());
ETLoc.setQualifierLoc(NNSLoc.getPrefix());
TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
@@ -3312,6 +3548,29 @@ namespace {
};
}
+static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
+ SourceLocation Loc;
+ switch (Chunk.Kind) {
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Paren:
+ llvm_unreachable("cannot be _Atomic qualified");
+
+ case DeclaratorChunk::Pointer:
+ Loc = SourceLocation::getFromRawEncoding(Chunk.Ptr.AtomicQualLoc);
+ break;
+
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::MemberPointer:
+ // FIXME: Provide a source location for the _Atomic keyword.
+ break;
+ }
+
+ ATL.setKWLoc(Loc);
+ ATL.setParensRange(SourceRange());
+}
+
/// \brief Create and instantiate a TypeSourceInfo with type source information.
///
/// \param T QualType referring to the type as written in source code.
@@ -3328,13 +3587,19 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
// Handle parameter packs whose type is a pack expansion.
if (isa<PackExpansionType>(T)) {
- cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc());
+ CurrTL.castAs<PackExpansionTypeLoc>().setEllipsisLoc(D.getEllipsisLoc());
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- while (isa<AttributedTypeLoc>(CurrTL)) {
- AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL);
+ // An AtomicTypeLoc might be produced by an atomic qualifier in this
+ // declarator chunk.
+ if (AtomicTypeLoc ATL = CurrTL.getAs<AtomicTypeLoc>()) {
+ fillAtomicQualLoc(ATL, D.getTypeObject(i));
+ CurrTL = ATL.getValueLoc().getUnqualifiedLoc();
+ }
+
+ while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs());
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -3389,7 +3654,11 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// Make sure there are no unused decl attributes on the declarator.
// We don't want to do this for ObjC parameters because we're going
// to apply them to the actual parameter declaration.
- if (D.getContext() != Declarator::ObjCParameterContext)
+ // Likewise, we don't want to do this for alias declarations, because
+ // we are actually going to build a declaration from this eventually.
+ if (D.getContext() != Declarator::ObjCParameterContext &&
+ D.getContext() != Declarator::AliasDeclContext &&
+ D.getContext() != Declarator::AliasTemplateContext)
checkUnusedDeclAttributes(D);
if (getLangOpts().CPlusPlus) {
@@ -3524,6 +3793,14 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
} else if (!type->isObjCRetainableType()) {
return false;
}
+
+ // Don't accept an ownership attribute in the declspec if it would
+ // just be the return type of a block pointer.
+ if (state.isProcessingDeclSpec()) {
+ Declarator &D = state.getDeclarator();
+ if (maybeMovePastReturnType(D, D.getNumTypeObjects()))
+ return false;
+ }
}
Sema &S = state.getSema();
@@ -3630,10 +3907,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
// Forbid __weak for class objects marked as
// objc_arc_weak_reference_unavailable
if (lifetime == Qualifiers::OCL_Weak) {
- QualType T = type;
- while (const PointerType *ptr = T->getAs<PointerType>())
- T = ptr->getPointeeType();
- if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
+ if (const ObjCObjectPointerType *ObjT =
+ type->getAs<ObjCObjectPointerType>()) {
if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) {
if (Class->isArcWeakrefUnavailable()) {
S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
@@ -4141,7 +4416,7 @@ static void HandleNeonVectorTypeAttr(QualType& CurType,
}
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
- bool isDeclSpec, AttributeList *attrs) {
+ TypeAttrLocation TAL, AttributeList *attrs) {
// Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the
// type, but others can be present in the type specifiers even though they
@@ -4156,10 +4431,45 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
if (attr.isInvalid())
continue;
+ if (attr.isCXX11Attribute()) {
+ // [[gnu::...]] attributes are treated as declaration attributes, so may
+ // not appertain to a DeclaratorChunk, even if we handle them as type
+ // attributes.
+ if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) {
+ if (TAL == TAL_DeclChunk) {
+ state.getSema().Diag(attr.getLoc(),
+ diag::warn_cxx11_gnu_attribute_on_type)
+ << attr.getName();
+ continue;
+ }
+ } else if (TAL != TAL_DeclChunk) {
+ // Otherwise, only consider type processing for a C++11 attribute if
+ // it's actually been applied to a type.
+ continue;
+ }
+ }
+
// If this is an attribute we can handle, do so now,
// otherwise, add it to the FnAttrs list for rechaining.
switch (attr.getKind()) {
- default: break;
+ default:
+ // A C++11 attribute on a declarator chunk must appertain to a type.
+ if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) {
+ state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr)
+ << attr.getName();
+ attr.setUsedAsTypeAttr();
+ }
+ break;
+
+ case AttributeList::UnknownAttribute:
+ if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
+ state.getSema().Diag(attr.getLoc(),
+ diag::warn_unknown_attribute_ignored)
+ << attr.getName();
+ break;
+
+ case AttributeList::IgnoredAttribute:
+ break;
case AttributeList::AT_MayAlias:
// FIXME: This attribute needs to actually be handled, but if we ignore
@@ -4180,9 +4490,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_ExtVectorType:
- if (state.getDeclarator().getDeclSpec().getStorageClassSpec()
- != DeclSpec::SCS_typedef)
- HandleExtVectorTypeAttr(type, attr, state.getSema());
+ HandleExtVectorTypeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_NeonVectorType:
@@ -4204,13 +4512,14 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case AttributeList::AT_Win64:
case AttributeList::AT_Ptr32:
case AttributeList::AT_Ptr64:
- // FIXME: don't ignore these
+ // FIXME: Don't ignore these. We have partial handling for them as
+ // declaration attributes in SemaDeclAttr.cpp; that should be moved here.
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
- break;
+ break;
// fallthrough into the function attrs
FUNCTION_TYPE_ATTRS_CASELIST:
@@ -4218,7 +4527,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// Never process function type attributes as part of the
// declaration-specifiers.
- if (isDeclSpec)
+ if (TAL == TAL_DeclSpec)
distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
// Otherwise, handle the possible delays.
@@ -4359,9 +4668,14 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
// repeating the diagnostic.
// FIXME: Add a Fix-It that imports the corresponding module or includes
// the header.
- if (isSFINAEContext() || HiddenDefinitions.insert(Def)) {
- Diag(Loc, diag::err_module_private_definition) << T;
- Diag(Def->getLocation(), diag::note_previous_definition);
+ Module *Owner = Def->getOwningModule();
+ Diag(Loc, diag::err_module_private_definition)
+ << T << Owner->getFullModuleName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+
+ if (!isSFINAEContext()) {
+ // Recover by implicitly importing this module.
+ createImplicitModuleImport(Loc, Owner);
}
}
@@ -4562,6 +4876,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
Diag(Dtor->getLocation(), Dtor->isUserProvided() ?
diag::note_non_literal_user_provided_dtor :
diag::note_non_literal_nontrivial_dtor) << RD;
+ if (!Dtor->isUserProvided())
+ SpecialMemberIsTrivial(Dtor, CXXDestructor, /*Diagnose*/true);
}
return true;
diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp
index 25ace950e077..2f7701227da6 100644
--- a/lib/Sema/TargetAttributesSema.cpp
+++ b/lib/Sema/TargetAttributesSema.cpp
@@ -13,9 +13,9 @@
//===----------------------------------------------------------------------===//
#include "TargetAttributesSema.h"
-#include "clang/Sema/SemaInternal.h"
-#include "clang/Basic/TargetInfo.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/Triple.h"
using namespace clang;
@@ -151,7 +151,8 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D,
S.Context));
}
-DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range) {
+DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
if (D->hasAttr<DLLExportAttr>()) {
Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
return NULL;
@@ -160,7 +161,8 @@ DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range) {
if (D->hasAttr<DLLImportAttr>())
return NULL;
- return ::new (Context) DLLImportAttr(Range, Context);
+ return ::new (Context) DLLImportAttr(Range, Context,
+ AttrSpellingListIndex);
}
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -189,12 +191,14 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange());
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
if (NewAttr)
D->addAttr(NewAttr);
}
-DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range) {
+DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
D->dropAttr<DLLImportAttr>();
@@ -203,7 +207,8 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range) {
if (D->hasAttr<DLLExportAttr>())
return NULL;
- return ::new (Context) DLLExportAttr(Range, Context);
+ return ::new (Context) DLLExportAttr(Range, Context,
+ AttrSpellingListIndex);
}
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -229,7 +234,8 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange());
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
if (NewAttr)
D->addAttr(NewAttr);
}
@@ -262,6 +268,57 @@ namespace {
};
}
+static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.hasParameterOrArguments()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+ // Attribute can only be applied to function types.
+ if (!isa<FunctionDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << /* function */0;
+ return;
+ }
+ D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.hasParameterOrArguments()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+ // Attribute can only be applied to function types.
+ if (!isa<FunctionDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << /* function */0;
+ return;
+ }
+ D->addAttr(::new (S.Context)
+ NoMips16Attr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+namespace {
+ class MipsAttributesSema : public TargetAttributesSema {
+ public:
+ MipsAttributesSema() { }
+ bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
+ Sema &S) const {
+ if (Attr.getName()->getName() == "mips16") {
+ HandleMips16Attr(D, Attr, S);
+ return true;
+ } else if (Attr.getName()->getName() == "nomips16") {
+ HandleNoMips16Attr(D, Attr, S);
+ return true;
+ }
+ return false;
+ }
+ };
+}
+
const TargetAttributesSema &Sema::getTargetAttributesSema() const {
if (TheTargetAttributesSema)
return *TheTargetAttributesSema;
@@ -275,6 +332,9 @@ const TargetAttributesSema &Sema::getTargetAttributesSema() const {
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return *(TheTargetAttributesSema = new X86AttributesSema);
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ return *(TheTargetAttributesSema = new MipsAttributesSema);
default:
return *(TheTargetAttributesSema = new TargetAttributesSema);
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 294d74244673..bdd68a7bde90 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -14,11 +14,7 @@
#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H
#define LLVM_CLANG_SEMA_TREETRANSFORM_H
-#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "clang/Sema/ScopeInfo.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -28,12 +24,16 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
-#include "clang/Sema/Ownership.h"
-#include "clang/Sema/Designator.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/ErrorHandling.h"
-#include "TypeLocBuilder.h"
#include <algorithm>
namespace clang {
@@ -247,10 +247,10 @@ public:
/// must be set.
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
- llvm::ArrayRef<UnexpandedParameterPack> Unexpanded,
+ ArrayRef<UnexpandedParameterPack> Unexpanded,
bool &ShouldExpand,
bool &RetainExpansion,
- llvm::Optional<unsigned> &NumExpansions) {
+ Optional<unsigned> &NumExpansions) {
ShouldExpand = false;
return false;
}
@@ -323,6 +323,15 @@ public:
/// \returns the transformed expression.
ExprResult TransformExpr(Expr *E);
+ /// \brief Transform the given initializer.
+ ///
+ /// By default, this routine transforms an initializer by stripping off the
+ /// semantic nodes added by initialization, then passing the result to
+ /// TransformExpr or TransformExprs.
+ ///
+ /// \returns the transformed initializer.
+ ExprResult TransformInitializer(Expr *Init, bool CXXDirectInit);
+
/// \brief Transform the given list of expressions.
///
/// This routine transforms a list of expressions by invoking
@@ -563,7 +572,7 @@ public:
/// scope index; can be negative
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
- llvm::Optional<unsigned> NumExpansions,
+ Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
@@ -704,12 +713,8 @@ public:
/// By default, performs semantic analysis when building the function type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildFunctionProtoType(QualType T,
- QualType *ParamTypes,
- unsigned NumParamTypes,
- bool Variadic, bool HasTrailingReturn,
- unsigned Quals,
- RefQualifierKind RefQualifier,
- const FunctionType::ExtInfo &Info);
+ llvm::MutableArrayRef<QualType> ParamTypes,
+ const FunctionProtoType::ExtProtoInfo &EPI);
/// \brief Build a new unprototyped function type.
QualType RebuildFunctionNoProtoType(QualType ResultType);
@@ -941,7 +946,7 @@ public:
QualType RebuildPackExpansionType(QualType Pattern,
SourceRange PatternRange,
SourceLocation EllipsisLoc,
- llvm::Optional<unsigned> NumExpansions) {
+ Optional<unsigned> NumExpansions) {
return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc,
NumExpansions);
}
@@ -2113,6 +2118,7 @@ public:
bool IsElidable,
MultiExprArg Args,
bool HadMultipleCandidates,
+ bool ListInitialization,
bool RequiresZeroInit,
CXXConstructExpr::ConstructionKind ConstructKind,
SourceRange ParenRange) {
@@ -2124,6 +2130,7 @@ public:
return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable,
ConvertedArgs,
HadMultipleCandidates,
+ ListInitialization,
RequiresZeroInit, ConstructKind,
ParenRange);
}
@@ -2214,7 +2221,7 @@ public:
ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack,
SourceLocation PackLoc,
SourceLocation RParenLoc,
- llvm::Optional<unsigned> Length) {
+ Optional<unsigned> Length) {
if (Length)
return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(),
OperatorLoc, Pack, PackLoc,
@@ -2382,13 +2389,14 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc,
+ SourceLocation OpLoc,
bool IsArrow) {
CXXScopeSpec SS;
ExprResult Base = getSema().Owned(BaseArg);
LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc,
Sema::LookupMemberName);
ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
- /*FIME:*/IsaLoc,
+ OpLoc,
SS, 0, false);
if (Result.isInvalid() || Base.isInvalid())
return ExprError();
@@ -2397,7 +2405,7 @@ public:
return Result;
return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
- /*FIXME:*/IsaLoc, IsArrow,
+ OpLoc, IsArrow,
SS, SourceLocation(),
/*FirstQualifierInScope=*/0,
R,
@@ -2416,10 +2424,10 @@ public:
= SemaRef.Context.Idents.get("__builtin_shufflevector");
TranslationUnitDecl *TUDecl = SemaRef.Context.getTranslationUnitDecl();
DeclContext::lookup_result Lookup = TUDecl->lookup(DeclarationName(&Name));
- assert(Lookup.first != Lookup.second && "No __builtin_shufflevector?");
+ assert(!Lookup.empty() && "No __builtin_shufflevector?");
// Build a reference to the __builtin_shufflevector builtin
- FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first);
+ FunctionDecl *Builtin = cast<FunctionDecl>(Lookup.front());
Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, false,
SemaRef.Context.BuiltinFnTy,
VK_RValue, BuiltinLoc);
@@ -2445,7 +2453,7 @@ public:
/// different behavior.
TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
SourceLocation EllipsisLoc,
- llvm::Optional<unsigned> NumExpansions) {
+ Optional<unsigned> NumExpansions) {
switch (Pattern.getArgument().getKind()) {
case TemplateArgument::Expression: {
ExprResult Result
@@ -2492,7 +2500,7 @@ public:
/// for an expression. Subclasses may override this routine to provide
/// different behavior.
ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
- llvm::Optional<unsigned> NumExpansions) {
+ Optional<unsigned> NumExpansions) {
return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions);
}
@@ -2549,7 +2557,7 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
if (E.isInvalid())
return StmtError();
- return getSema().ActOnExprStmt(getSema().MakeFullExpr(E.take()));
+ return getSema().ActOnExprStmt(E);
}
}
@@ -2575,6 +2583,65 @@ ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
}
template<typename Derived>
+ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
+ bool CXXDirectInit) {
+ // Initializers are instantiated like expressions, except that various outer
+ // layers are stripped.
+ if (!Init)
+ return SemaRef.Owned(Init);
+
+ if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
+ Init = ExprTemp->getSubExpr();
+
+ while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
+ Init = Binder->getSubExpr();
+
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
+ Init = ICE->getSubExprAsWritten();
+
+ // If this is not a direct-initializer, we only need to reconstruct
+ // InitListExprs. Other forms of copy-initialization will be a no-op if
+ // the initializer is already the right type.
+ CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init);
+ if (!CXXDirectInit && !(Construct && Construct->isListInitialization()))
+ return getDerived().TransformExpr(Init);
+
+ // Revert value-initialization back to empty parens.
+ if (CXXScalarValueInitExpr *VIE = dyn_cast<CXXScalarValueInitExpr>(Init)) {
+ SourceRange Parens = VIE->getSourceRange();
+ return getDerived().RebuildParenListExpr(Parens.getBegin(), MultiExprArg(),
+ Parens.getEnd());
+ }
+
+ // FIXME: We shouldn't build ImplicitValueInitExprs for direct-initialization.
+ if (isa<ImplicitValueInitExpr>(Init))
+ return getDerived().RebuildParenListExpr(SourceLocation(), MultiExprArg(),
+ SourceLocation());
+
+ // Revert initialization by constructor back to a parenthesized or braced list
+ // of expressions. Any other form of initializer can just be reused directly.
+ if (!Construct || isa<CXXTemporaryObjectExpr>(Construct))
+ return getDerived().TransformExpr(Init);
+
+ SmallVector<Expr*, 8> NewArgs;
+ bool ArgChanged = false;
+ if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(),
+ /*IsCall*/true, NewArgs, &ArgChanged))
+ return ExprError();
+
+ // If this was list initialization, revert to list form.
+ if (Construct->isListInitialization())
+ return getDerived().RebuildInitList(Construct->getLocStart(), NewArgs,
+ Construct->getLocEnd(),
+ Construct->getType());
+
+ // Build a ParenListExpr to represent anything else.
+ SourceRange Parens = Construct->getParenRange();
+ return getDerived().RebuildParenListExpr(Parens.getBegin(), NewArgs,
+ Parens.getEnd());
+}
+
+template<typename Derived>
bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
unsigned NumInputs,
bool IsCall,
@@ -2600,9 +2667,8 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
- llvm::Optional<unsigned> OrigNumExpansions
- = Expansion->getNumExpansions();
- llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+ Optional<unsigned> OrigNumExpansions = Expansion->getNumExpansions();
+ Optional<unsigned> NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(),
Pattern->getSourceRange(),
Unexpanded,
@@ -2656,7 +2722,9 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
continue;
}
- ExprResult Result = getDerived().TransformExpr(Inputs[I]);
+ ExprResult Result =
+ IsCall ? getDerived().TransformInitializer(Inputs[I], /*DirectInit*/false)
+ : getDerived().TransformExpr(Inputs[I]);
if (Result.isInvalid())
return true;
@@ -2732,7 +2800,7 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
return NestedNameSpecifierLoc();
if (TL.getType()->isDependentType() || TL.getType()->isRecordType() ||
- (SemaRef.getLangOpts().CPlusPlus0x &&
+ (SemaRef.getLangOpts().CPlusPlus11 &&
TL.getType()->isEnumeralType())) {
assert(!TL.getType().hasLocalQualifiers() &&
"Can't get cv-qualifiers here");
@@ -2745,8 +2813,8 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
}
// If the nested-name-specifier is an invalid type def, don't emit an
// error because a previous error should have already been emitted.
- TypedefTypeLoc* TTL = dyn_cast<TypedefTypeLoc>(&TL);
- if (!TTL || !TTL->getTypedefNameDecl()->isInvalidDecl()) {
+ TypedefTypeLoc TTL = TL.getAs<TypedefTypeLoc>();
+ if (!TTL || !TTL.getTypedefNameDecl()->isInvalidDecl()) {
SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag)
<< TL.getType() << SS.getRange();
}
@@ -3119,7 +3187,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
// We have a pack expansion, for which we will be substituting into
// the pattern.
SourceLocation Ellipsis;
- llvm::Optional<unsigned> OrigNumExpansions;
+ Optional<unsigned> OrigNumExpansions;
TemplateArgumentLoc Pattern
= In.getPackExpansionPattern(Ellipsis, OrigNumExpansions,
getSema().Context);
@@ -3132,7 +3200,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+ Optional<unsigned> NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(Ellipsis,
Pattern.getSourceRange(),
Unexpanded,
@@ -3254,9 +3322,10 @@ QualType
TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
switch (T.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
- case TypeLoc::CLASS: \
- return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T));
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: \
+ return getDerived().Transform##CLASS##Type(TLB, \
+ T.castAs<CLASS##TypeLoc>());
#include "clang/AST/TypeLocNodes.def"
}
@@ -3293,6 +3362,7 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
// Objective-C ARC:
// A lifetime qualifier applied to a substituted template parameter
// overrides the lifetime qualifier from the template argument.
+ const AutoType *AutoTy;
if (const SubstTemplateTypeParmType *SubstTypeParam
= dyn_cast<SubstTemplateTypeParmType>(Result)) {
QualType Replacement = SubstTypeParam->getReplacementType();
@@ -3305,6 +3375,15 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
SubstTypeParam->getReplacedParameter(),
Replacement);
TLB.TypeWasModifiedSafely(Result);
+ } else if ((AutoTy = dyn_cast<AutoType>(Result)) && AutoTy->isDeduced()) {
+ // 'auto' types behave the same way as template parameters.
+ QualType Deduced = AutoTy->getDeducedType();
+ Qualifiers Qs = Deduced.getQualifiers();
+ Qs.removeObjCLifetime();
+ Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
+ Qs);
+ Result = SemaRef.Context.getAutoType(Deduced);
+ TLB.TypeWasModifiedSafely(Result);
} else {
// Otherwise, complain about the addition of a qualifier to an
// already-qualified type.
@@ -3318,7 +3397,9 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
}
if (!Quals.empty()) {
Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals);
- TLB.push<QualifiedTypeLoc>(Result);
+ // BuildQualifiedType might not add qualifiers if they are invalid.
+ if (Result.hasLocalQualifiers())
+ TLB.push<QualifiedTypeLoc>(Result);
// No location information to preserve.
}
@@ -3339,8 +3420,8 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
QualType Result;
if (isa<TemplateSpecializationType>(T)) {
- TemplateSpecializationTypeLoc SpecTL
- = cast<TemplateSpecializationTypeLoc>(TL);
+ TemplateSpecializationTypeLoc SpecTL =
+ TL.castAs<TemplateSpecializationTypeLoc>();
TemplateName Template =
getDerived().TransformTemplateName(SS,
@@ -3353,8 +3434,8 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
Template);
} else if (isa<DependentTemplateSpecializationType>(T)) {
- DependentTemplateSpecializationTypeLoc SpecTL
- = cast<DependentTemplateSpecializationTypeLoc>(TL);
+ DependentTemplateSpecializationTypeLoc SpecTL =
+ TL.castAs<DependentTemplateSpecializationTypeLoc>();
TemplateName Template
= getDerived().RebuildTemplateName(SS,
@@ -3396,8 +3477,8 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
TypeLoc TL = TSInfo->getTypeLoc();
if (isa<TemplateSpecializationType>(T)) {
- TemplateSpecializationTypeLoc SpecTL
- = cast<TemplateSpecializationTypeLoc>(TL);
+ TemplateSpecializationTypeLoc SpecTL =
+ TL.castAs<TemplateSpecializationTypeLoc>();
TemplateName Template
= getDerived().TransformTemplateName(SS,
@@ -3410,8 +3491,8 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
Template);
} else if (isa<DependentTemplateSpecializationType>(T)) {
- DependentTemplateSpecializationTypeLoc SpecTL
- = cast<DependentTemplateSpecializationTypeLoc>(TL);
+ DependentTemplateSpecializationTypeLoc SpecTL =
+ TL.castAs<DependentTemplateSpecializationTypeLoc>();
TemplateName Template
= getDerived().RebuildTemplateName(SS,
@@ -3864,12 +3945,10 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
return Result;
}
-template<typename Derived>
-ParmVarDecl *
-TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
- int indexAdjustment,
- llvm::Optional<unsigned> NumExpansions,
- bool ExpectParameterPack) {
+template <typename Derived>
+ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam(
+ ParmVarDecl *OldParm, int indexAdjustment, Optional<unsigned> NumExpansions,
+ bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
TypeSourceInfo *NewDI = 0;
@@ -3877,7 +3956,7 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
// If we're substituting into a pack expansion type and we know the
// length we want to expand to, just substitute for the pattern.
TypeLoc OldTL = OldDI->getTypeLoc();
- PackExpansionTypeLoc OldExpansionTL = cast<PackExpansionTypeLoc>(OldTL);
+ PackExpansionTypeLoc OldExpansionTL = OldTL.castAs<PackExpansionTypeLoc>();
TypeLocBuilder TLB;
TypeLoc NewTL = OldDI->getTypeLoc();
@@ -3915,7 +3994,6 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
NewDI->getType(),
NewDI,
OldParm->getStorageClass(),
- OldParm->getStorageClassAsWritten(),
/* DefArg */ NULL);
newParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
OldParm->getFunctionScopeIndex() + indexAdjustment);
@@ -3935,7 +4013,7 @@ bool TreeTransform<Derived>::
if (ParmVarDecl *OldParm = Params[i]) {
assert(OldParm->getFunctionScopeIndex() == i);
- llvm::Optional<unsigned> NumExpansions;
+ Optional<unsigned> NumExpansions;
ParmVarDecl *NewParm = 0;
if (OldParm->isParameterPack()) {
// We have a function parameter pack that may need to be expanded.
@@ -3943,7 +4021,7 @@ bool TreeTransform<Derived>::
// Find the parameter packs that could be expanded.
TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc();
- PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(TL);
+ PackExpansionTypeLoc ExpansionTL = TL.castAs<PackExpansionTypeLoc>();
TypeLoc Pattern = ExpansionTL.getPatternLoc();
SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
assert(Unexpanded.size() > 0 && "Could not find parameter packs!");
@@ -3951,8 +4029,8 @@ bool TreeTransform<Derived>::
// Determine whether we should expand the parameter packs.
bool ShouldExpand = false;
bool RetainExpansion = false;
- llvm::Optional<unsigned> OrigNumExpansions
- = ExpansionTL.getTypePtr()->getNumExpansions();
+ Optional<unsigned> OrigNumExpansions =
+ ExpansionTL.getTypePtr()->getNumExpansions();
NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
Pattern.getSourceRange(),
@@ -4017,10 +4095,8 @@ bool TreeTransform<Derived>::
NumExpansions,
/*ExpectParameterPack=*/true);
} else {
- NewParm = getDerived().TransformFunctionTypeParam(OldParm,
- indexAdjustment,
- llvm::Optional<unsigned>(),
- /*ExpectParameterPack=*/false);
+ NewParm = getDerived().TransformFunctionTypeParam(
+ OldParm, indexAdjustment, None, /*ExpectParameterPack=*/ false);
}
if (!NewParm)
@@ -4036,7 +4112,7 @@ bool TreeTransform<Derived>::
// declaration for this parameter.
QualType OldType = ParamTypes[i];
bool IsPackExpansion = false;
- llvm::Optional<unsigned> NumExpansions;
+ Optional<unsigned> NumExpansions;
QualType NewType;
if (const PackExpansionType *Expansion
= dyn_cast<PackExpansionType>(OldType)) {
@@ -4188,14 +4264,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
ResultType != T->getResultType() ||
T->getNumArgs() != ParamTypes.size() ||
!std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
- Result = getDerived().RebuildFunctionProtoType(ResultType,
- ParamTypes.data(),
- ParamTypes.size(),
- T->isVariadic(),
- T->hasTrailingReturn(),
- T->getTypeQuals(),
- T->getRefQualifier(),
- T->getExtInfo());
+ Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes,
+ T->getExtProtoInfo());
if (Result.isNull())
return QualType();
}
@@ -4561,7 +4631,6 @@ QualType TreeTransform<Derived>::TransformAtomicType(TypeLocBuilder &TLB,
return Result;
}
-namespace {
/// \brief Simple iterator that traverses the template arguments in a
/// container that provides a \c getArgLoc() member function.
///
@@ -4625,7 +4694,6 @@ namespace {
return !(X == Y);
}
};
-}
template <typename Derived>
@@ -5379,7 +5447,7 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
if (Inc.isInvalid())
return StmtError();
- Sema::FullExprArg FullInc(getSema().MakeFullExpr(Inc.get()));
+ Sema::FullExprArg FullInc(getSema().MakeFullDiscardedValueExpr(Inc.get()));
if (S->getInc() && !FullInc.get())
return StmtError();
@@ -6946,17 +7014,13 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
Type == E->getTypeInfoAsWritten() &&
SubExpr.get() == E->getSubExpr())
return SemaRef.Owned(E);
-
- // FIXME: Poor source location information here.
- SourceLocation FakeLAngleLoc
- = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
- SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin();
return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(),
E->getStmtClass(),
- FakeLAngleLoc,
+ E->getAngleBrackets().getBegin(),
Type,
- FakeRAngleLoc,
- FakeRAngleLoc,
+ E->getAngleBrackets().getEnd(),
+ // FIXME. this should be '(' location
+ E->getAngleBrackets().getEnd(),
SubExpr.get(),
E->getRParenLoc());
}
@@ -7105,9 +7169,14 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
QualType T;
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
T = MD->getThisType(getSema().Context);
- else
+ else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) {
T = getSema().Context.getPointerType(
- getSema().Context.getRecordType(cast<CXXRecordDecl>(DC)));
+ getSema().Context.getRecordType(Record));
+ } else {
+ assert(SemaRef.Context.getDiagnostics().hasErrorOccurred() &&
+ "this in the wrong scope?");
+ return ExprError();
+ }
if (!getDerived().AlwaysRebuild() && T == E->getType()) {
// Make sure that we capture 'this'.
@@ -7387,7 +7456,9 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
TypeSourceInfo *ScopeTypeInfo = 0;
if (E->getScopeTypeInfo()) {
- ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo());
+ CXXScopeSpec EmptySS;
+ ScopeTypeInfo = getDerived().TransformTypeInObjectScope(
+ E->getScopeTypeInfo(), ObjectType, 0, EmptySS);
if (!ScopeTypeInfo)
return ExprError();
}
@@ -7524,11 +7595,11 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
bool ArgChanged = false;
- llvm::SmallVector<TypeSourceInfo *, 4> Args;
+ SmallVector<TypeSourceInfo *, 4> Args;
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
TypeSourceInfo *From = E->getArg(I);
TypeLoc FromTL = From->getTypeLoc();
- if (!isa<PackExpansionTypeLoc>(FromTL)) {
+ if (!FromTL.getAs<PackExpansionTypeLoc>()) {
TypeLocBuilder TLB;
TLB.reserve(FromTL.getFullDataSize());
QualType To = getDerived().TransformType(TLB, FromTL);
@@ -7547,7 +7618,7 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
ArgChanged = true;
// We have a pack expansion. Instantiate it.
- PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(FromTL);
+ PackExpansionTypeLoc ExpansionTL = FromTL.castAs<PackExpansionTypeLoc>();
TypeLoc PatternTL = ExpansionTL.getPatternLoc();
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
SemaRef.collectUnexpandedParameterPacks(PatternTL, Unexpanded);
@@ -7556,9 +7627,9 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
- llvm::Optional<unsigned> OrigNumExpansions
- = ExpansionTL.getTypePtr()->getNumExpansions();
- llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+ Optional<unsigned> OrigNumExpansions =
+ ExpansionTL.getTypePtr()->getNumExpansions();
+ Optional<unsigned> NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
PatternTL.getSourceRange(),
Unexpanded,
@@ -7747,10 +7818,13 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
- // CXXConstructExprs are always implicit, so when we have a
- // 1-argument construction we just transform that argument.
- if (E->getNumArgs() == 1 ||
- (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1))))
+ // CXXConstructExprs other than for list-initialization and
+ // CXXTemporaryObjectExpr are always implicit, so when we have
+ // a 1-argument construction we just transform that argument.
+ if ((E->getNumArgs() == 1 ||
+ (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1)))) &&
+ (!getDerived().DropCallArgument(E->getArg(0))) &&
+ !E->isListInitialization())
return getDerived().TransformExpr(E->getArg(0));
TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
@@ -7786,6 +7860,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
Constructor, E->isElidable(),
Args,
E->hadMultipleCandidates(),
+ E->isListInitialization(),
E->requiresZeroInitialization(),
E->getConstructionKind(),
E->getParenRange());
@@ -7843,6 +7918,7 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
return SemaRef.MaybeBindToTemporary(E);
}
+ // FIXME: Pass in E->isListInitialization().
return getDerived().RebuildCXXTemporaryObjectExpr(T,
/*FIXME:*/T->getTypeLoc().getEndLoc(),
Args,
@@ -7867,8 +7943,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
// Transform lambda parameters.
- llvm::SmallVector<QualType, 4> ParamTypes;
- llvm::SmallVector<ParmVarDecl *, 4> Params;
+ SmallVector<QualType, 4> ParamTypes;
+ SmallVector<ParmVarDecl *, 4> Params;
if (getDerived().TransformFunctionTypeParams(E->getLocStart(),
E->getCallOperator()->param_begin(),
E->getCallOperator()->param_size(),
@@ -7931,7 +8007,7 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
UnexpandedParameterPack Unexpanded(C->getCapturedVar(), C->getLocation());
bool ShouldExpand = false;
bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions;
+ Optional<unsigned> NumExpansions;
if (getDerived().TryExpandParameterPacks(C->getEllipsisLoc(),
C->getLocation(),
Unexpanded,
@@ -8274,7 +8350,7 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
bool ShouldExpand = false;
bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions;
+ Optional<unsigned> NumExpansions;
if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(),
Unexpanded,
ShouldExpand, RetainExpansion,
@@ -8360,7 +8436,7 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformObjCArrayLiteral(ObjCArrayLiteral *E) {
// Transform each of the elements.
- llvm::SmallVector<Expr *, 8> Elements;
+ SmallVector<Expr *, 8> Elements;
bool ArgChanged = false;
if (getDerived().TransformExprs(E->getElements(), E->getNumElements(),
/*IsCall=*/false, Elements, &ArgChanged))
@@ -8379,7 +8455,7 @@ ExprResult
TreeTransform<Derived>::TransformObjCDictionaryLiteral(
ObjCDictionaryLiteral *E) {
// Transform each of the elements.
- llvm::SmallVector<ObjCDictionaryElement, 8> Elements;
+ SmallVector<ObjCDictionaryElement, 8> Elements;
bool ArgChanged = false;
for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
ObjCDictionaryElement OrigElement = E->getKeyValueElement(I);
@@ -8395,8 +8471,8 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
// and should be expanded.
bool Expand = true;
bool RetainExpansion = false;
- llvm::Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions;
- llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+ Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions;
+ Optional<unsigned> NumExpansions = OrigNumExpansions;
SourceRange PatternRange(OrigElement.Key->getLocStart(),
OrigElement.Value->getLocEnd());
if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc,
@@ -8483,7 +8559,7 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
ArgChanged = true;
ObjCDictionaryElement Element = {
- Key.get(), Value.get(), SourceLocation(), llvm::Optional<unsigned>()
+ Key.get(), Value.get(), SourceLocation(), None
};
Elements.push_back(Element);
}
@@ -8712,6 +8788,7 @@ TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
return SemaRef.Owned(E);
return getDerived().RebuildObjCIsaExpr(Base.get(), E->getIsaMemberLoc(),
+ E->getOpLoc(),
E->isArrow());
}
@@ -8758,7 +8835,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
return ExprError();
}
- const FunctionType *exprFunctionType = E->getFunctionType();
+ const FunctionProtoType *exprFunctionType = E->getFunctionType();
QualType exprResultType =
getDerived().TransformType(exprFunctionType->getResultType());
@@ -8771,13 +8848,9 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
return ExprError();
}
- QualType functionType = getDerived().RebuildFunctionProtoType(
- exprResultType,
- paramTypes.data(),
- paramTypes.size(),
- oldBlock->isVariadic(),
- false, 0, RQ_None,
- exprFunctionType->getExtInfo());
+ QualType functionType =
+ getDerived().RebuildFunctionProtoType(exprResultType, paramTypes,
+ exprFunctionType->getExtProtoInfo());
blockScope->FunctionType = functionType;
// Set the parameters on the block decl.
@@ -8993,19 +9066,14 @@ TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
}
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
- QualType *ParamTypes,
- unsigned NumParamTypes,
- bool Variadic,
- bool HasTrailingReturn,
- unsigned Quals,
- RefQualifierKind RefQualifier,
- const FunctionType::ExtInfo &Info) {
- return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
- HasTrailingReturn, Quals, RefQualifier,
+QualType TreeTransform<Derived>::RebuildFunctionProtoType(
+ QualType T,
+ llvm::MutableArrayRef<QualType> ParamTypes,
+ const FunctionProtoType::ExtProtoInfo &EPI) {
+ return SemaRef.BuildFunctionType(T, ParamTypes,
getDerived().getBaseLocation(),
getDerived().getBaseEntity(),
- Info);
+ EPI);
}
template<typename Derived>
diff --git a/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h
index 7a5e43e25dc9..f36ec9f3e209 100644
--- a/lib/Sema/TypeLocBuilder.h
+++ b/lib/Sema/TypeLocBuilder.h
@@ -15,8 +15,8 @@
#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
-#include "clang/AST/TypeLoc.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/TypeLoc.h"
namespace clang {
@@ -75,7 +75,7 @@ class TypeLocBuilder {
/// previously retrieved from this builder.
TypeSpecTypeLoc pushTypeSpec(QualType T) {
size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
- return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
+ return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>();
}
/// Resets this builder to the newly-initialized state.
@@ -97,8 +97,8 @@ class TypeLocBuilder {
/// Pushes space for a new TypeLoc of the given type. Invalidates
/// any TypeLocs previously retrieved from this builder.
template <class TyLocType> TyLocType push(QualType T) {
- size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
- return cast<TyLocType>(pushImpl(T, LocalSize));
+ size_t LocalSize = TypeLoc(T, 0).castAs<TyLocType>().getLocalDataSize();
+ return pushImpl(T, LocalSize).castAs<TyLocType>();
}
/// Creates a TypeSourceInfo for the given type.