summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-01-01 10:34:51 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-01-01 10:34:51 +0000
commitbb1e3bc1e0be2b8f891db46457a8943451bf4d8b (patch)
tree1e68501209c9133fbda8d45171e59f8d6f12dd55 /lib/Sema
parent77212133072dc40f070a280af8217032f55a9eb4 (diff)
downloadFreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.zip
FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.tar.gz
Updaet clang to 92395.
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp17
-rw-r--r--lib/Sema/Lookup.h68
-rw-r--r--lib/Sema/Sema.cpp13
-rw-r--r--lib/Sema/Sema.h175
-rw-r--r--lib/Sema/SemaAccess.cpp2
-rw-r--r--lib/Sema/SemaCXXCast.cpp15
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp50
-rw-r--r--lib/Sema/SemaChecking.cpp3
-rw-r--r--lib/Sema/SemaCodeComplete.cpp79
-rw-r--r--lib/Sema/SemaDecl.cpp342
-rw-r--r--lib/Sema/SemaDeclAttr.cpp19
-rw-r--r--lib/Sema/SemaDeclCXX.cpp449
-rw-r--r--lib/Sema/SemaDeclObjC.cpp13
-rw-r--r--lib/Sema/SemaExpr.cpp639
-rw-r--r--lib/Sema/SemaExprCXX.cpp274
-rw-r--r--lib/Sema/SemaExprObjC.cpp2
-rw-r--r--lib/Sema/SemaInit.cpp1140
-rw-r--r--lib/Sema/SemaInit.h181
-rw-r--r--lib/Sema/SemaLookup.cpp662
-rw-r--r--lib/Sema/SemaOverload.cpp397
-rw-r--r--lib/Sema/SemaStmt.cpp31
-rw-r--r--lib/Sema/SemaTemplate.cpp93
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp156
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp5
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp29
-rw-r--r--lib/Sema/SemaType.cpp39
-rw-r--r--lib/Sema/TreeTransform.h96
27 files changed, 3356 insertions, 1633 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index d8ed894..b9b85df 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -37,6 +37,7 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
case CK_Text:
case CK_Placeholder:
case CK_Informative:
+ case CK_ResultType:
case CK_CurrentParameter: {
char *New = new char [Text.size() + 1];
std::memcpy(New, Text.data(), Text.size());
@@ -112,6 +113,11 @@ CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
}
CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateResultType(StringRef ResultType) {
+ return Chunk(CK_ResultType, ResultType);
+}
+
+CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateCurrentParameter(
StringRef CurrentParameter) {
return Chunk(CK_CurrentParameter, CurrentParameter);
@@ -123,6 +129,7 @@ CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const {
case CK_Text:
case CK_Placeholder:
case CK_Informative:
+ case CK_ResultType:
case CK_CurrentParameter:
case CK_LeftParen:
case CK_RightParen:
@@ -156,6 +163,7 @@ CodeCompletionString::Chunk::Destroy() {
case CK_Text:
case CK_Placeholder:
case CK_Informative:
+ case CK_ResultType:
case CK_CurrentParameter:
delete [] Text;
break;
@@ -186,7 +194,12 @@ std::string CodeCompletionString::getAsString() const {
switch (C->Kind) {
case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
- case CK_Informative: OS << "[#" << C->Text << "#]"; break;
+
+ case CK_Informative:
+ case CK_ResultType:
+ OS << "[#" << C->Text << "#]";
+ break;
+
case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
default: OS << C->Text; break;
}
@@ -236,6 +249,7 @@ void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
case CK_Text:
case CK_Placeholder:
case CK_Informative:
+ case CK_ResultType:
case CK_CurrentParameter: {
const char *Text = C->Text;
unsigned StrLen = strlen(Text);
@@ -286,6 +300,7 @@ CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str,
case CK_Text:
case CK_Placeholder:
case CK_Informative:
+ case CK_ResultType:
case CK_CurrentParameter: {
unsigned StrLen;
if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd))
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index 78f79ea..c5eecda 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -121,6 +121,8 @@ public:
typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
typedef DeclsTy::const_iterator iterator;
+ typedef bool (*ResultFilter)(NamedDecl*, unsigned IDNS);
+
LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
Sema::LookupNameKind LookupKind,
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
@@ -130,11 +132,14 @@ public:
Name(Name),
NameLoc(NameLoc),
LookupKind(LookupKind),
+ IsAcceptableFn(0),
IDNS(0),
Redecl(Redecl != Sema::NotForRedeclaration),
HideTags(true),
Diagnose(Redecl == Sema::NotForRedeclaration)
- {}
+ {
+ configure();
+ }
/// Creates a temporary lookup result, initializing its core data
/// using the information from another result. Diagnostics are always
@@ -146,6 +151,7 @@ public:
Name(Other.Name),
NameLoc(Other.NameLoc),
LookupKind(Other.LookupKind),
+ IsAcceptableFn(Other.IsAcceptableFn),
IDNS(Other.IDNS),
Redecl(Other.Redecl),
HideTags(Other.HideTags),
@@ -162,6 +168,11 @@ public:
return Name;
}
+ /// \brief Sets the name to look up.
+ void setLookupName(DeclarationName Name) {
+ this->Name = Name;
+ }
+
/// Gets the kind of lookup to perform.
Sema::LookupNameKind getLookupKind() const {
return LookupKind;
@@ -178,17 +189,6 @@ public:
HideTags = Hide;
}
- /// The identifier namespace of this lookup. This information is
- /// private to the lookup routines.
- unsigned getIdentifierNamespace() const {
- assert(IDNS);
- return IDNS;
- }
-
- void setIdentifierNamespace(unsigned NS) {
- IDNS = NS;
- }
-
bool isAmbiguous() const {
return getResultKind() == Ambiguous;
}
@@ -231,7 +231,19 @@ public:
return Paths;
}
- /// \brief Add a declaration to these results.
+ /// \brief Tests whether the given declaration is acceptable.
+ bool isAcceptableDecl(NamedDecl *D) const {
+ assert(IsAcceptableFn);
+ return IsAcceptableFn(D, IDNS);
+ }
+
+ /// \brief Returns the identifier namespace mask for this lookup.
+ unsigned getIdentifierNamespace() const {
+ return IDNS;
+ }
+
+ /// \brief Add a declaration to these results. Does not test the
+ /// acceptance criteria.
void addDecl(NamedDecl *D) {
Decls.push_back(D);
ResultKind = Found;
@@ -334,6 +346,7 @@ public:
void clear(Sema::LookupNameKind Kind) {
clear();
LookupKind = Kind;
+ configure();
}
void print(llvm::raw_ostream &);
@@ -362,6 +375,10 @@ public:
return NameLoc;
}
+ /// \brief Get the Sema object that this lookup result is searching
+ /// with.
+ Sema &getSema() const { return SemaRef; }
+
/// A class for iterating through a result set and possibly
/// filtering out results. The results returned are possibly
/// sugared.
@@ -438,6 +455,7 @@ private:
}
void addDeclsFromBasePaths(const CXXBasePaths &P);
+ void configure();
// Sanity checks.
void sanity() const {
@@ -476,7 +494,9 @@ private:
SourceLocation NameLoc;
SourceRange NameContextRange;
Sema::LookupNameKind LookupKind;
- unsigned IDNS; // ill-defined until set by lookup
+ ResultFilter IsAcceptableFn; // set by configure()
+ unsigned IDNS; // set by configure()
+
bool Redecl;
/// \brief True if tag declarations should be hidden if non-tags
@@ -486,6 +506,26 @@ private:
bool Diagnose;
};
+ /// \brief Consumes visible declarations found when searching for
+ /// all visible names within a given scope or context.
+ ///
+ /// This abstract class is meant to be subclassed by clients of \c
+ /// Sema::LookupVisibleDecls(), each of which should override the \c
+ /// FoundDecl() function to process declarations as they are found.
+ class VisibleDeclConsumer {
+ public:
+ /// \brief Destroys the visible declaration consumer.
+ virtual ~VisibleDeclConsumer();
+
+ /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
+ /// declaration visible from the current scope or context.
+ ///
+ /// \param ND the declaration found.
+ ///
+ /// \param Hiding a declaration that hides the declaration \p ND,
+ /// or NULL if no such declaration exists.
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding) = 0;
+ };
}
#endif
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index ef61474..40ad90a 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -350,7 +350,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
- PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0),
+ CurBlock(0), PackContext(0), ParsingDeclDepth(0),
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
@@ -389,12 +389,6 @@ static bool getIntProperties(ASTContext &C, const Type *T,
return true;
}
- if (const FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
- BitWidth = FWIT->getWidth();
- Signed = FWIT->isSigned();
- return true;
- }
-
return false;
}
@@ -655,8 +649,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T) {
}
// If the target is integral, always warn.
- if ((TargetBT && TargetBT->isInteger()) ||
- isa<FixedWidthIntType>(Target))
+ if ((TargetBT && TargetBT->isInteger()))
// TODO: don't warn for integer values?
return DiagnoseImpCast(S, E, T, diag::warn_impcast_float_integer);
@@ -815,7 +808,7 @@ void Sema::ActOnEndOfTranslationUnit() {
//===----------------------------------------------------------------------===//
DeclContext *Sema::getFunctionLevelDeclContext() {
- DeclContext *DC = PreDeclaratorDC ? PreDeclaratorDC : CurContext;
+ DeclContext *DC = CurContext;
while (isa<BlockDecl>(DC))
DC = DC->getParent();
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index ada8aa1..4cecee4 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -24,6 +24,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/FullExpr.h"
#include "clang/Parse/Action.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallVector.h"
@@ -57,6 +58,7 @@ namespace clang {
class DesignatedInitExpr;
class CallExpr;
class DeclRefExpr;
+ class UnresolvedLookupExpr;
class VarDecl;
class ParmVarDecl;
class TypedefDecl;
@@ -98,7 +100,8 @@ namespace clang {
class InitializedEntity;
class InitializationKind;
class InitializationSequence;
-
+ class VisibleDeclConsumer;
+
/// BlockSemaInfo - When a block is being parsed, this contains information
/// about the block. It is pointed to from Sema::CurBlock.
struct BlockSemaInfo {
@@ -190,10 +193,6 @@ public:
/// CurContext - This is the current declaration context of parsing.
DeclContext *CurContext;
- /// PreDeclaratorDC - Keeps the declaration context before switching to the
- /// context of a declarator's nested-name-specifier.
- DeclContext *PreDeclaratorDC;
-
/// CurBlock - If inside of a block definition, this contains a pointer to
/// the active block object that represents it.
BlockSemaInfo *CurBlock;
@@ -611,10 +610,6 @@ public:
const LookupResult &Previous,
Scope *S);
void DiagnoseFunctionSpecifiers(Declarator& D);
- bool CheckRedeclaration(DeclContext *DC,
- DeclarationName Name,
- SourceLocation NameLoc,
- unsigned Diagnostic);
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, TypeSourceInfo *TInfo,
LookupResult &Previous, bool &Redeclaration);
@@ -763,6 +758,12 @@ public:
/// struct, or union).
virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl);
+ /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
+ /// C++ record definition's base-specifiers clause and are starting its
+ /// member declarations.
+ virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl,
+ SourceLocation LBraceLoc);
+
/// ActOnTagFinishDefinition - Invoked once we have finished parsing
/// the definition of a tag (enumeration, class, struct, or union).
virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl,
@@ -841,6 +842,18 @@ public:
void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
+ // AssignmentAction - This is used by all the assignment diagnostic functions
+ // to represent what is actually causing the operation
+ enum AssignmentAction {
+ AA_Assigning,
+ AA_Passing,
+ AA_Returning,
+ AA_Converting,
+ AA_Initializing,
+ AA_Sending,
+ AA_Casting
+ };
+
/// C++ Overloading.
enum OverloadKind {
/// This is a legitimate overload: the existing declarations are
@@ -917,9 +930,13 @@ public:
TryCopyInitialization(Expr* From, QualType ToType,
bool SuppressUserConversions, bool ForceRValue,
bool InOverloadResolution);
+
bool PerformCopyInitialization(Expr *&From, QualType ToType,
- const char *Flavor, bool Elidable = false);
+ AssignmentAction Action, bool Elidable = false);
+ OwningExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ OwningExprResult Init);
ImplicitConversionSequence
TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method,
CXXRecordDecl *ActingContext);
@@ -1020,27 +1037,23 @@ public:
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
bool Complain);
+ FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From);
+
Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
OwningExprResult FixOverloadedFunctionReference(OwningExprResult,
FunctionDecl *Fn);
- void AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*>& Callees,
- DeclarationName &UnqualifiedName,
- bool ArgumentDependentLookup,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading = false);
- FunctionDecl *ResolveOverloadedCallFn(Expr *Fn,
- llvm::SmallVectorImpl<NamedDecl*> &Fns,
- DeclarationName UnqualifiedName,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
- SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc,
- bool ArgumentDependentLookup);
+ OwningExprResult BuildOverloadedCallExpr(Expr *Fn,
+ UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
unsigned Opc,
@@ -1133,7 +1146,7 @@ public:
// members.
LookupOperatorName,
/// Look up of a name that precedes the '::' scope resolution
- /// operator in C++. This lookup completely ignores operator,
+ /// operator in C++. This lookup completely ignores operator, object,
/// function, and enumerator names (C++ [basic.lookup.qual]p1).
LookupNestedNameSpecifierName,
/// Look up a namespace name within a C++ using directive or
@@ -1164,36 +1177,6 @@ private:
bool CppLookupName(LookupResult &R, Scope *S);
public:
- /// Determines whether D is a suitable lookup result according to the
- /// lookup criteria.
- static bool isAcceptableLookupResult(NamedDecl *D, LookupNameKind NameKind,
- unsigned IDNS) {
- switch (NameKind) {
- case Sema::LookupOrdinaryName:
- case Sema::LookupTagName:
- case Sema::LookupMemberName:
- case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
- case Sema::LookupUsingDeclName:
- case Sema::LookupObjCProtocolName:
- case Sema::LookupObjCImplementationName:
- return D->isInIdentifierNamespace(IDNS);
-
- case Sema::LookupOperatorName:
- return D->isInIdentifierNamespace(IDNS) &&
- !D->getDeclContext()->isRecord();
-
- case Sema::LookupNestedNameSpecifierName:
- return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag);
-
- case Sema::LookupNamespaceName:
- return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D);
- }
-
- assert(false &&
- "isAcceptableLookupResult always returns before this point");
- return false;
- }
-
/// \brief Look up a name, looking for a single declaration. Return
/// null if the results were absent, ambiguous, or overloaded.
///
@@ -1215,11 +1198,20 @@ public:
void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
FunctionSet &Functions);
-
+
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
FunctionSet &Functions);
+ void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer);
+ void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer);
+
+ bool CorrectTypo(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
+ DeclContext *MemberContext = 0,
+ bool EnteringContext = false);
+
void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
AssociatedNamespaceSet &AssociatedNamespaces,
AssociatedClassSet &AssociatedClasses);
@@ -1455,7 +1447,8 @@ public:
virtual void PopExpressionEvaluationContext();
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
-
+ bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
+
// Primary Expressions.
virtual SourceRange getExprRange(ExprTy *E) const;
@@ -1465,6 +1458,8 @@ public:
bool HasTrailingLParen,
bool IsAddressOfOperand);
+ bool DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS, LookupResult &R);
+
OwningExprResult LookupInObjCMethod(LookupResult &R,
Scope *S,
IdentifierInfo *II);
@@ -1485,6 +1480,9 @@ public:
FieldDecl *Field,
Expr *BaseObjectExpr = 0,
SourceLocation OpLoc = SourceLocation());
+ OwningExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs);
OwningExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
@@ -1611,16 +1609,6 @@ public:
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc);
- void DeconstructCallFunction(Expr *FnExpr,
- llvm::SmallVectorImpl<NamedDecl*>& Fns,
- DeclarationName &Name,
- NestedNameSpecifier *&Qualifier,
- SourceRange &QualifierRange,
- bool &ArgumentDependentLookup,
- bool &Overloaded,
- bool &HasExplicitTemplateArgs,
- TemplateArgumentListInfo &ExplicitTemplateArgs);
-
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
@@ -1812,7 +1800,8 @@ public:
OwningExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc,
QualType DeclInitType,
CXXConstructorDecl *Constructor,
- MultiExprArg Exprs);
+ MultiExprArg Exprs,
+ bool RequiresZeroInit = false);
// FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
// the constructor can be elidable?
@@ -1820,7 +1809,8 @@ public:
QualType DeclInitType,
CXXConstructorDecl *Constructor,
bool Elidable,
- MultiExprArg Exprs);
+ MultiExprArg Exprs,
+ bool RequiresZeroInit = false);
OwningExprResult BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Cons,
QualType writtenTy,
@@ -1972,7 +1962,8 @@ public:
bool AllowMissing, FunctionDecl *&Operator);
void DeclareGlobalNewDelete();
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
- QualType Argument);
+ QualType Argument,
+ bool addMallocAttr = false);
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
DeclarationName Name, FunctionDecl* &Operator);
@@ -2003,9 +1994,10 @@ public:
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.
- Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
- bool ShouldDestroyTemporaries);
-
+ Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr);
+ OwningExprResult MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr);
+ FullExpr CreateFullExpr(Expr *SubExpr);
+
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr);
bool RequireCompleteDeclContext(const CXXScopeSpec &SS);
@@ -2216,11 +2208,15 @@ public:
SourceLocation RBrac);
virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template);
+ virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
+ DeclPtrTy Record);
virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
DeclPtrTy Method);
virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param);
virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
DeclPtrTy Method);
+ virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
+ DeclPtrTy Record);
virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
ExprArg AssertExpr,
@@ -2681,7 +2677,10 @@ public:
TDK_TooFewArguments,
/// \brief The explicitly-specified template arguments were not valid
/// template arguments for the given template.
- TDK_InvalidExplicitArguments
+ TDK_InvalidExplicitArguments,
+ /// \brief The arguments included an overloaded function name that could
+ /// not be resolved to a suitable function.
+ TDK_FailedOverloadResolution
};
/// \brief Provides information about an attempted template argument
@@ -2795,6 +2794,12 @@ public:
CXXConversionDecl *&Specialization,
TemplateDeductionInfo &Info);
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info);
+
FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC);
@@ -3555,14 +3560,14 @@ public:
/// represent it in the AST.
Incompatible
};
-
+
/// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the
/// assignment conversion type specified by ConvTy. This returns true if the
/// conversion was invalid or false if the conversion was accepted.
bool DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
- Expr *SrcExpr, const char *Flavor);
+ Expr *SrcExpr, AssignmentAction Action);
/// CheckAssignmentConstraints - Perform type checking for assignment,
/// argument passing, variable initialization, and function return values.
@@ -3597,25 +3602,24 @@ public:
bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
- const char *Flavor,
+ AssignmentAction Action,
bool AllowExplicit = false,
bool Elidable = false);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
- const char *Flavor,
+ AssignmentAction Action,
bool AllowExplicit,
bool Elidable,
ImplicitConversionSequence& ICS);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
const ImplicitConversionSequence& ICS,
- const char *Flavor,
+ AssignmentAction Action,
bool IgnoreBaseAccess = false);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
const StandardConversionSequence& SCS,
- const char *Flavor, bool IgnoreBaseAccess);
+ AssignmentAction Action, bool IgnoreBaseAccess);
bool BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
- const ImplicitConversionSequence& ICS,
- const char *Flavor);
+ const ImplicitConversionSequence& ICS);
/// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued).
@@ -3675,15 +3679,10 @@ public:
SourceLocation CmpLoc);
/// type checking declaration initializers (C99 6.7.8)
-
- bool CheckInitializerTypes(Expr *&simpleInit_or_initList, QualType &declType,
- SourceLocation InitLoc,DeclarationName InitEntity,
- bool DirectInit);
- bool CheckInitList(InitListExpr *&InitList, QualType &DeclType);
+ bool CheckInitList(const InitializedEntity &Entity,
+ InitListExpr *&InitList, QualType &DeclType);
bool CheckForConstantInitializer(Expr *e, QualType t);
- bool CheckValueInitialization(QualType Type, SourceLocation Loc);
-
// type checking C++ declaration initializers (C++ [dcl.init]).
/// ReferenceCompareResult - Expresses the result of comparing two
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 21f83a5..b7cc37b 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -37,6 +37,8 @@ bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
<< MemberDecl << LexicalAS;
Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
<< PrevMemberDecl << PrevMemberDecl->getAccess();
+
+ MemberDecl->setAccess(LexicalAS);
return true;
}
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 814af90..800c544 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -899,7 +899,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// The conversion is possible, so commit to it.
Kind = CastExpr::CK_NoOp;
msg = 0;
- return Self.PerformImplicitConversion(SrcExpr, DestType, ICS, "casting",
+ return Self.PerformImplicitConversion(SrcExpr, DestType, ICS, Sema::AA_Casting,
/*IgnoreBaseAccess*/CStyle) ?
TC_Failed : TC_Success;
}
@@ -959,8 +959,9 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
// as must be the final pointee type.
while (SrcType != DestType &&
Self.UnwrapSimilarPointerTypes(SrcType, DestType)) {
- SrcType = SrcType.getUnqualifiedType();
- DestType = DestType.getUnqualifiedType();
+ Qualifiers Quals;
+ SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals);
+ DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals);
}
// Since we're dealing in canonical types, the remainder must be the same.
@@ -975,8 +976,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
const SourceRange &OpRange,
unsigned &msg,
CastExpr::CastKind &Kind) {
- QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
-
DestType = Self.Context.getCanonicalType(DestType);
QualType SrcType = SrcExpr->getType();
if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
@@ -1053,8 +1052,11 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
return TC_NotApplicable;
// If both types have the same size, we can successfully cast.
- if (Self.Context.getTypeSize(SrcType) == Self.Context.getTypeSize(DestType))
+ if (Self.Context.getTypeSize(SrcType)
+ == Self.Context.getTypeSize(DestType)) {
+ Kind = CastExpr::CK_BitCast;
return TC_Success;
+ }
if (destIsScalar)
msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
@@ -1083,6 +1085,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
// to the same type. However, the behavior of compilers is pretty consistent
// on this point: allow same-type conversion if the involved types are
// pointers, disallow otherwise.
+ Kind = CastExpr::CK_NoOp;
return TC_Success;
}
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 039691f..82d58ea 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -329,7 +329,7 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
/// that it contains an extra parameter \p ScopeLookupResult, which provides
/// the result of name lookup within the scope of the nested-name-specifier
-/// that was computed at template definitino time.
+/// that was computed at template definition time.
///
/// If ErrorRecoveryLookup is true, then this call is used to improve error
/// recovery. This means that it should not emit diagnostics, it should
@@ -428,6 +428,28 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
}
// FIXME: Deal with ambiguities cleanly.
+
+ if (Found.empty() && !ErrorRecoveryLookup) {
+ // We haven't found anything, and we're not recovering from a
+ // different kind of error, so look for typos.
+ DeclarationName Name = Found.getLookupName();
+ if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext) &&
+ Found.isSingleResult() &&
+ isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) {
+ if (LookupCtx)
+ Diag(Found.getNameLoc(), diag::err_no_member_suggest)
+ << Name << LookupCtx << Found.getLookupName() << SS.getRange()
+ << CodeModificationHint::CreateReplacement(Found.getNameLoc(),
+ Found.getLookupName().getAsString());
+ else
+ Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest)
+ << Name << Found.getLookupName()
+ << CodeModificationHint::CreateReplacement(Found.getNameLoc(),
+ Found.getLookupName().getAsString());
+ } else
+ Found.clear();
+ }
+
NamedDecl *SD = Found.getAsSingle<NamedDecl>();
if (isAcceptableNestedNameSpecifier(SD)) {
if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) {
@@ -605,15 +627,18 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
/// The 'SS' should be a non-empty valid CXXScopeSpec.
bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
- if (DeclContext *DC = computeDeclContext(SS, true)) {
- // Before we enter a declarator's context, we need to make sure that
- // it is a complete declaration context.
- if (!DC->isDependentContext() && RequireCompleteDeclContext(SS))
- return true;
-
- EnterDeclaratorContext(S, DC);
- }
-
+
+ if (SS.isInvalid()) return true;
+
+ DeclContext *DC = computeDeclContext(SS, true);
+ if (!DC) return true;
+
+ // Before we enter a declarator's context, we need to make sure that
+ // it is a complete declaration context.
+ if (!DC->isDependentContext() && RequireCompleteDeclContext(SS))
+ return true;
+
+ EnterDeclaratorContext(S, DC);
return false;
}
@@ -626,6 +651,7 @@ void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
if (SS.isInvalid())
return;
- if (computeDeclContext(SS, true))
- ExitDeclaratorContext(S);
+ assert(!SS.isInvalid() && computeDeclContext(SS, true) &&
+ "exiting declarator scope we never really entered");
+ ExitDeclaratorContext(S);
}
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 28de500..f10fa07 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -747,6 +747,7 @@ bool Sema::SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall) {
/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr,
/// int type). This simply type checks that type is one of the defined
/// constants (0-3).
+// For compatability check 0-3, llvm only handles 0 and 2.
bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
Expr *Arg = TheCall->getArg(1);
if (Arg->isTypeDependent())
@@ -800,7 +801,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
switch (E->getStmtClass()) {
case Stmt::ConditionalOperatorClass: {
const ConditionalOperator *C = cast<ConditionalOperator>(E);
- return SemaCheckStringLiteral(C->getLHS(), TheCall,
+ return SemaCheckStringLiteral(C->getTrueExpr(), TheCall,
HasVAListArg, format_idx, firstDataArg)
&& SemaCheckStringLiteral(C->getRHS(), TheCall,
HasVAListArg, format_idx, firstDataArg);
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 4ce9330..ef82a94 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -829,6 +829,39 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, unsigned Rank,
}
}
+/// \brief If the given declaration has an associated type, add it as a result
+/// type chunk.
+static void AddResultTypeChunk(ASTContext &Context,
+ NamedDecl *ND,
+ CodeCompletionString *Result) {
+ if (!ND)
+ return;
+
+ // Determine the type of the declaration (if it has a type).
+ QualType T;
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ T = Function->getResultType();
+ else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ T = Method->getResultType();
+ else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ T = FunTmpl->getTemplatedDecl()->getResultType();
+ else if (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))
+ T = Value->getType();
+ else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+ T = Property->getType();
+
+ if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
+ return;
+
+ std::string TypeStr;
+ T.getAsStringInternal(TypeStr, Context.PrintingPolicy);
+ Result->AddResultTypeChunk(TypeStr);
+}
+
/// \brief Add function parameter chunks to the given code completion string.
static void AddFunctionParameterChunks(ASTContext &Context,
FunctionDecl *Function,
@@ -1042,6 +1075,8 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
return Result;
}
+ AddResultTypeChunk(S.Context, ND, Result);
+
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
@@ -1170,6 +1205,13 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
Result->AddPlaceholderChunk(Arg);
}
+ if (Method->isVariadic()) {
+ if (AllParametersAreInformative)
+ Result->AddInformativeChunk(", ...");
+ else
+ Result->AddPlaceholderChunk(", ...");
+ }
+
return Result;
}
@@ -1189,6 +1231,7 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
CodeCompletionString *Result = new CodeCompletionString;
FunctionDecl *FDecl = getFunction();
+ AddResultTypeChunk(S.Context, FDecl, Result);
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(getFunctionType());
if (!FDecl && !Proto) {
@@ -1706,33 +1749,24 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
CodeCompleteOrdinaryName(S);
return;
}
-
- llvm::SmallVector<NamedDecl*,8> Fns;
- DeclarationName UnqualifiedName;
- NestedNameSpecifier *Qualifier;
- SourceRange QualifierRange;
- bool ArgumentDependentLookup;
- bool Overloaded;
- bool HasExplicitTemplateArgs;
- TemplateArgumentListInfo ExplicitTemplateArgs;
-
- DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange,
- ArgumentDependentLookup, Overloaded,
- HasExplicitTemplateArgs, ExplicitTemplateArgs);
-
+ // Build an overload candidate set based on the functions we find.
+ OverloadCandidateSet CandidateSet;
+
// FIXME: What if we're calling something that isn't a function declaration?
// FIXME: What if we're calling a pseudo-destructor?
// FIXME: What if we're calling a member function?
- // Build an overload candidate set based on the functions we find.
- OverloadCandidateSet CandidateSet;
- AddOverloadedCallCandidates(Fns, UnqualifiedName,
- ArgumentDependentLookup,
- (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0),
- Args, NumArgs,
- CandidateSet,
- /*PartialOverloading=*/true);
+ Expr *NakedFn = Fn->IgnoreParenCasts();
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
+ AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
+ /*PartialOverloading=*/ true);
+ else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
+ FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (FDecl)
+ AddOverloadCandidate(FDecl, Args, NumArgs, CandidateSet,
+ false, false, /*PartialOverloading*/ true);
+ }
// Sort the overload candidate set by placing the best overloads first.
std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
@@ -2419,7 +2453,6 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
typedef CodeCompleteConsumer::Result Result;
Expr *RecExpr = static_cast<Expr *>(Receiver);
- QualType RecType = RecExpr->getType();
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 14d2377..2253f09 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -35,6 +35,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
#include <algorithm>
#include <cstring>
#include <functional>
@@ -106,8 +107,12 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS))
return 0;
}
-
- LookupResult Result(*this, &II, NameLoc, LookupOrdinaryName);
+
+ // FIXME: LookupNestedNameSpecifierName isn't the right kind of
+ // lookup for class-names.
+ LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName :
+ LookupOrdinaryName;
+ LookupResult Result(*this, &II, NameLoc, Kind);
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
// computed, which is either the type of the base of a member access
@@ -250,10 +255,41 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
// We don't have anything to suggest (yet).
SuggestedType = 0;
+ // There may have been a typo in the name of the type. Look up typo
+ // results, in case we have something that we can suggest.
+ LookupResult Lookup(*this, &II, IILoc, LookupOrdinaryName,
+ NotForRedeclaration);
+
+ // FIXME: It would be nice if we could correct for typos in built-in
+ // names, such as "itn" for "int".
+
+ if (CorrectTypo(Lookup, S, SS) && Lookup.isSingleResult()) {
+ NamedDecl *Result = Lookup.getAsSingle<NamedDecl>();
+ if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) &&
+ !Result->isInvalidDecl()) {
+ // We found a similarly-named type or interface; suggest that.
+ if (!SS || !SS->isSet())
+ Diag(IILoc, diag::err_unknown_typename_suggest)
+ << &II << Lookup.getLookupName()
+ << CodeModificationHint::CreateReplacement(SourceRange(IILoc),
+ Result->getNameAsString());
+ else if (DeclContext *DC = computeDeclContext(*SS, false))
+ Diag(IILoc, diag::err_unknown_nested_typename_suggest)
+ << &II << DC << Lookup.getLookupName() << SS->getRange()
+ << CodeModificationHint::CreateReplacement(SourceRange(IILoc),
+ Result->getNameAsString());
+ else
+ llvm_unreachable("could not have corrected a typo here");
+
+ SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS);
+ return true;
+ }
+ }
+
// FIXME: Should we move the logic that tries to recover from a missing tag
// (struct, union, enum) from Parser::ParseImplicitInt here, instead?
- if (!SS)
+ if (!SS || (!SS->isSet() && !SS->isInvalid()))
Diag(IILoc, diag::err_unknown_typename) << &II;
else if (DeclContext *DC = computeDeclContext(*SS, false))
Diag(IILoc, diag::err_typename_nested_not_found)
@@ -321,23 +357,47 @@ void Sema::PopDeclContext() {
/// EnterDeclaratorContext - Used when we must lookup names in the context
/// of a declarator's nested name specifier.
+///
void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
- assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
- PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
+ // C++0x [basic.lookup.unqual]p13:
+ // A name used in the definition of a static data member of class
+ // X (after the qualified-id of the static member) is looked up as
+ // if the name was used in a member function of X.
+ // C++0x [basic.lookup.unqual]p14:
+ // If a variable member of a namespace is defined outside of the
+ // scope of its namespace then any name used in the definition of
+ // the variable member (after the declarator-id) is looked up as
+ // if the definition of the variable member occurred in its
+ // namespace.
+ // Both of these imply that we should push a scope whose context
+ // is the semantic context of the declaration. We can't use
+ // PushDeclContext here because that context is not necessarily
+ // lexically contained in the current context. Fortunately,
+ // the containing scope should have the appropriate information.
+
+ assert(!S->getEntity() && "scope already has entity");
+
+#ifndef NDEBUG
+ Scope *Ancestor = S->getParent();
+ while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+ assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
+#endif
+
CurContext = DC;
- assert(CurContext && "No context?");
- S->setEntity(CurContext);
+ S->setEntity(DC);
}
void Sema::ExitDeclaratorContext(Scope *S) {
- S->setEntity(PreDeclaratorDC);
- PreDeclaratorDC = 0;
+ assert(S->getEntity() == CurContext && "Context imbalance!");
- // Reset CurContext to the nearest enclosing context.
- while (!S->getEntity() && S->getParent())
- S = S->getParent();
- CurContext = static_cast<DeclContext*>(S->getEntity());
- assert(CurContext && "No context?");
+ // Switch back to the lexical context. The safety of this is
+ // enforced by an assert in EnterDeclaratorContext.
+ Scope *Ancestor = S->getParent();
+ while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+ CurContext = (DeclContext*) Ancestor->getEntity();
+
+ // We don't need to do anything with the scope, which is going to
+ // disappear.
}
/// \brief Determine whether we allow overloading of the function
@@ -667,9 +727,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
}
// Verify the old decl was also a type.
- TypeDecl *Old = 0;
- if (!OldDecls.isSingleResult() ||
- !(Old = dyn_cast<TypeDecl>(OldDecls.getFoundDecl()))) {
+ TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>();
+ if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
@@ -704,6 +763,13 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
return New->setInvalidDecl();
}
+ // The types match. Link up the redeclaration chain if the old
+ // declaration was a typedef.
+ // FIXME: this is a potential source of wierdness if the type
+ // spellings don't match exactly.
+ if (isa<TypedefDecl>(Old))
+ New->setPreviousDeclaration(cast<TypedefDecl>(Old));
+
if (getLangOptions().Microsoft)
return;
@@ -772,7 +838,7 @@ static Sema::CXXSpecialMember getSpecialMember(ASTContext &Ctx,
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
if (Ctor->isDefaultConstructor())
return Sema::CXXDefaultConstructor;
- if (Ctor->isCopyConstructor(Ctx))
+ if (Ctor->isCopyConstructor())
return Sema::CXXCopyConstructor;
}
@@ -901,7 +967,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
// (C++98 8.3.5p3):
// All declarations for a function shall agree exactly in both the
// return type and the parameter-type-list.
- if (OldQType == NewQType)
+ // attributes should be ignored when comparing.
+ if (Context.getNoReturnType(OldQType, false) ==
+ Context.getNoReturnType(NewQType, false))
return MergeCompatibleFunctionDecls(New, Old);
// Fall through for conflicting redeclarations and redefinitions.
@@ -1253,11 +1321,6 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
HasFakeEdge = true;
continue;
}
- if (isa<AsmStmt>(S)) {
- HasFakeEdge = true;
- HasLiveReturn = true;
- continue;
- }
bool NoReturnEdge = false;
if (CallExpr *C = dyn_cast<CallExpr>(S)) {
Expr *CEE = C->getCallee()->IgnoreParenCasts();
@@ -1445,7 +1508,6 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
// FIXME: Error on auto/register at file scope
// FIXME: Error on inline/virtual/explicit
- // FIXME: Error on invalid restrict
// FIXME: Warn on useless __thread
// FIXME: Warn on useless const/volatile
// FIXME: Warn on useless static/extern/typedef/private_extern/mutable
@@ -1467,6 +1529,15 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
Tag = dyn_cast<TagDecl>(TagD);
}
+ 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."
+ if (TypeQuals & DeclSpec::TQ_restrict)
+ Diag(DS.getRestrictSpecLoc(),
+ diag::err_typecheck_invalid_restrict_not_pointer_noarg)
+ << DS.getSourceRange();
+ }
+
if (DS.isFriendSpecified()) {
// If we're dealing with a class template decl, assume that the
// template routines are handling it.
@@ -1516,29 +1587,27 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
return DeclPtrTy::make(Tag);
}
-/// We are trying to introduce the given name into the given context;
+/// We are trying to inject an anonymous member into the given scope;
/// check if there's an existing declaration that can't be overloaded.
///
/// \return true if this is a forbidden redeclaration
-bool Sema::CheckRedeclaration(DeclContext *DC,
- DeclarationName Name,
- SourceLocation NameLoc,
- unsigned diagnostic) {
- LookupResult R(*this, Name, NameLoc, LookupOrdinaryName,
- ForRedeclaration);
- LookupQualifiedName(R, DC);
-
- if (R.empty()) return false;
-
- if (R.getResultKind() == LookupResult::Found &&
- isa<TagDecl>(R.getFoundDecl()))
+static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
+ Scope *S,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ unsigned diagnostic) {
+ LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
+ Sema::ForRedeclaration);
+ if (!SemaRef.LookupName(R, S)) return false;
+
+ if (R.getAsSingle<TagDecl>())
return false;
// Pick a representative declaration.
- NamedDecl *PrevDecl = (*R.begin())->getUnderlyingDecl();
+ NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl();
- Diag(NameLoc, diagnostic) << Name;
- Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+ SemaRef.Diag(NameLoc, diagnostic) << Name;
+ SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
return true;
}
@@ -1570,8 +1639,8 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
FEnd = AnonRecord->field_end();
F != FEnd; ++F) {
if ((*F)->getDeclName()) {
- if (CheckRedeclaration(Owner, (*F)->getDeclName(),
- (*F)->getLocation(), diagKind)) {
+ if (CheckAnonMemberRedeclaration(*this, S, (*F)->getDeclName(),
+ (*F)->getLocation(), diagKind)) {
// C++ [class.union]p2:
// The names of the members of an anonymous union shall be
// distinct from the names of any other entity in the
@@ -1889,9 +1958,12 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
if (DeclContext *DC = computeDeclContext(D.getCXXScopeSpec(), true)) {
// FIXME: Preserve type source info.
QualType T = GetTypeFromParser(DS.getTypeRep());
- EnterDeclaratorContext(S, DC);
+
+ DeclContext *SavedContext = CurContext;
+ CurContext = DC;
T = RebuildTypeInCurrentInstantiation(T, D.getIdentifierLoc(), Name);
- ExitDeclaratorContext(S);
+ CurContext = SavedContext;
+
if (T.isNull())
return DeclPtrTy();
DS.UpdateTypeRep(T.getAsOpaquePtr());
@@ -3364,7 +3436,16 @@ void Sema::CheckMain(FunctionDecl* FD) {
unsigned nparams = FTP->getNumArgs();
assert(FD->getNumParams() == nparams);
- if (nparams > 3) {
+ bool HasExtraParameters = (nparams > 3);
+
+ // Darwin passes an undocumented fourth argument of type char**. If
+ // other platforms start sprouting these, the logic below will start
+ // getting shifty.
+ if (nparams == 4 &&
+ Context.Target.getTriple().getOS() == llvm::Triple::Darwin)
+ HasExtraParameters = false;
+
+ if (HasExtraParameters) {
Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams;
FD->setInvalidDecl(true);
nparams = 3;
@@ -3375,7 +3456,7 @@ void Sema::CheckMain(FunctionDecl* FD) {
QualType CharPP =
Context.getPointerType(Context.getPointerType(Context.CharTy));
- QualType Expected[] = { Context.IntTy, CharPP, CharPP };
+ QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP };
for (unsigned i = 0; i < nparams; ++i) {
QualType AT = FTP->getArgType(i);
@@ -3504,6 +3585,18 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
Expr *Init = init.takeAs<Expr>();
assert(Init && "missing initializer");
+ // Capture the variable that is being initialized and the style of
+ // initialization.
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
+
+ // FIXME: Poor source location information.
+ InitializationKind Kind
+ = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(),
+ Init->getLocStart(),
+ Init->getLocEnd())
+ : InitializationKind::CreateCopy(VDecl->getLocation(),
+ Init->getLocStart());
+
// Get the decls type and save a reference for later, since
// CheckInitializerTypes may change it.
QualType DclT = VDecl->getType(), SavT = DclT;
@@ -3512,37 +3605,16 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
VDecl->setInvalidDecl();
} else if (!VDecl->isInvalidDecl()) {
- if (VDecl->getType()->isReferenceType()
- || isa<InitListExpr>(Init)) {
- InitializedEntity Entity
- = InitializedEntity::InitializeVariable(VDecl);
-
- // FIXME: Poor source location information.
- InitializationKind Kind
- = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(),
- SourceLocation(),
- SourceLocation())
- : InitializationKind::CreateCopy(VDecl->getLocation(),
- SourceLocation());
- InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
- if (InitSeq) {
- OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, (void**)&Init, 1),
- &DclT);
- if (Result.isInvalid()) {
- VDecl->setInvalidDecl();
- return;
- }
-
- Init = Result.takeAs<Expr>();
- } else {
- InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
- VDecl->setInvalidDecl();
- return;
- }
- } else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
- VDecl->getDeclName(), DirectInit))
+ InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, (void**)&Init, 1),
+ &DclT);
+ if (Result.isInvalid()) {
VDecl->setInvalidDecl();
+ return;
+ }
+
+ Init = Result.takeAs<Expr>();
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
// Don't check invalid declarations to avoid emitting useless diagnostics.
@@ -3601,10 +3673,18 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
} else if (VDecl->isFileVarDecl()) {
if (VDecl->getStorageClass() == VarDecl::Extern)
Diag(VDecl->getLocation(), diag::warn_extern_init);
- if (!VDecl->isInvalidDecl())
- if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
- VDecl->getDeclName(), DirectInit))
+ if (!VDecl->isInvalidDecl()) {
+ InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, (void**)&Init, 1),
+ &DclT);
+ if (Result.isInvalid()) {
VDecl->setInvalidDecl();
+ return;
+ }
+
+ Init = Result.takeAs<Expr>();
+ }
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
// Don't check invalid declarations to avoid emitting useless diagnostics.
@@ -3622,8 +3702,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
Init->setType(DclT);
}
- Init = MaybeCreateCXXExprWithTemporaries(Init,
- /*ShouldDestroyTemporaries=*/true);
+ Init = MaybeCreateCXXExprWithTemporaries(Init);
// Attach the initializer to the decl.
VDecl->setInit(Context, Init);
@@ -3635,6 +3714,15 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted;
}
+ if (getLangOptions().CPlusPlus) {
+ // Make sure we mark the destructor as used if necessary.
+ QualType InitType = VDecl->getType();
+ if (const ArrayType *Array = Context.getAsArrayType(InitType))
+ InitType = Context.getBaseElementType(Array);
+ if (InitType->isRecordType())
+ FinalizeVarWithDestructor(VDecl, InitType);
+ }
+
return;
}
@@ -3722,28 +3810,19 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
InitType->isRecordType() && !InitType->isDependentType()) {
if (!RequireCompleteType(Var->getLocation(), InitType,
diag::err_invalid_incomplete_type_use)) {
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
-
- CXXConstructorDecl *Constructor
- = PerformInitializationByConstructor(InitType,
- MultiExprArg(*this, 0, 0),
- Var->getLocation(),
- SourceRange(Var->getLocation(),
- Var->getLocation()),
- Var->getDeclName(),
- InitializationKind::CreateDefault(Var->getLocation()),
- ConstructorArgs);
-
- // FIXME: Location info for the variable initialization?
- if (!Constructor)
+ InitializedEntity Entity
+ = InitializedEntity::InitializeVariable(Var);
+ InitializationKind Kind
+ = InitializationKind::CreateDefault(Var->getLocation());
+
+ InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
+ OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, 0, 0));
+ if (Init.isInvalid())
Var->setInvalidDecl();
else {
- // FIXME: Cope with initialization of arrays
- if (!Constructor->isTrivial() &&
- InitializeVarWithConstructor(Var, Constructor,
- move_arg(ConstructorArgs)))
- Var->setInvalidDecl();
-
+ Var->setInit(Context,
+ MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>()));
FinalizeVarWithDestructor(Var, InitType);
}
} else {
@@ -4382,6 +4461,10 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
if (Context.BuiltinInfo.isNoReturn(BuiltinID))
FD->addAttr(::new (Context) NoReturnAttr());
+ if (Context.BuiltinInfo.isNoThrow(BuiltinID))
+ FD->addAttr(::new (Context) NoThrowAttr());
+ if (Context.BuiltinInfo.isConst(BuiltinID))
+ FD->addAttr(::new (Context) ConstAttr());
}
IdentifierInfo *Name = FD->getIdentifier();
@@ -4939,31 +5022,36 @@ void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) {
// Enter the tag context.
PushDeclContext(S, Tag);
+}
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Tag)) {
- FieldCollector->StartClass();
-
- if (Record->getIdentifier()) {
- // C++ [class]p2:
- // [...] The class-name is also inserted into the scope of the
- // class itself; this is known as the injected-class-name. For
- // purposes of access checking, the injected-class-name is treated
- // as if it were a public member name.
- CXXRecordDecl *InjectedClassName
- = CXXRecordDecl::Create(Context, Record->getTagKind(),
- CurContext, Record->getLocation(),
- Record->getIdentifier(),
- Record->getTagKeywordLoc(),
- Record);
- InjectedClassName->setImplicit();
- InjectedClassName->setAccess(AS_public);
- if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
- InjectedClassName->setDescribedClassTemplate(Template);
- PushOnScopeChains(InjectedClassName, S);
- assert(InjectedClassName->isInjectedClassName() &&
- "Broken injected-class-name");
- }
- }
+void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD,
+ SourceLocation LBraceLoc) {
+ AdjustDeclIfTemplate(TagD);
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD.getAs<Decl>());
+
+ FieldCollector->StartClass();
+
+ if (!Record->getIdentifier())
+ return;
+
+ // C++ [class]p2:
+ // [...] The class-name is also inserted into the scope of the
+ // class itself; this is known as the injected-class-name. For
+ // purposes of access checking, the injected-class-name is treated
+ // as if it were a public member name.
+ CXXRecordDecl *InjectedClassName
+ = CXXRecordDecl::Create(Context, Record->getTagKind(),
+ CurContext, Record->getLocation(),
+ Record->getIdentifier(),
+ Record->getTagKeywordLoc(),
+ Record);
+ InjectedClassName->setImplicit();
+ InjectedClassName->setAccess(AS_public);
+ if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
+ InjectedClassName->setDescribedClassTemplate(Template);
+ PushOnScopeChains(InjectedClassName, S);
+ assert(InjectedClassName->isInjectedClassName() &&
+ "Broken injected-class-name");
}
void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD,
@@ -5808,7 +5896,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
const llvm::APSInt &InitVal = ECD->getInitVal();
assert(InitVal.getBitWidth() >= IntWidth &&
"Should have promoted value to int");
- if (InitVal.getBitWidth() > IntWidth) {
+ if (!getLangOptions().CPlusPlus && InitVal.getBitWidth() > IntWidth) {
llvm::APSInt V(InitVal);
V.trunc(IntWidth);
V.extend(InitVal.getBitWidth());
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 84ee207..094e5b5 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -47,7 +47,7 @@ static const FunctionType *getFunctionType(const Decl *d,
// FIXME: We should provide an abstraction around a method or function
// to provide the following bits of information.
-/// isFunctionOrMethod - Return true if the given decl has function
+/// isFunction - Return true if the given decl has function
/// type (function or function-typed variable).
static bool isFunction(const Decl *d) {
return getFunctionType(d, false) != NULL;
@@ -730,15 +730,19 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
return;
}
- // TODO: could also be applied to methods?
- FunctionDecl *Fn = dyn_cast<FunctionDecl>(D);
- if (!Fn) {
+ if (!isFunctionOrMethod(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << 0 /*function*/;
return;
}
- Fn->addAttr(::new (S.Context) WarnUnusedResultAttr());
+ if (getFunctionType(D)->getResultType()->isVoidType()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_void_function)
+ << Attr.getName();
+ return;
+ }
+
+ D->addAttr(::new (S.Context) WarnUnusedResultAttr());
}
static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -1610,7 +1614,10 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
return;
}
- NewTy = S.Context.getFixedWidthIntType(128, OldTy->isSignedIntegerType());
+ if (OldTy->isSignedIntegerType())
+ NewTy = S.Context.Int128Ty;
+ else
+ NewTy = S.Context.UnsignedInt128Ty;
break;
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 228a716..204d776 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -109,8 +109,6 @@ namespace {
bool
Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
SourceLocation EqualLoc) {
- QualType ParamType = Param->getType();
-
if (RequireCompleteType(Param->getLocation(), Param->getType(),
diag::err_typecheck_decl_incomplete_type)) {
Param->setInvalidDecl();
@@ -125,11 +123,17 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
// the same semantic constraints as the initializer expression in
// a declaration of a variable of the parameter type, using the
// copy-initialization semantics (8.5).
- if (CheckInitializerTypes(Arg, ParamType, EqualLoc,
- Param->getDeclName(), /*DirectInit=*/false))
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(Param);
+ InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
+ EqualLoc);
+ InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1);
+ OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, (void**)&Arg, 1));
+ if (Result.isInvalid())
return true;
+ Arg = Result.takeAs<Expr>();
- Arg = MaybeCreateCXXExprWithTemporaries(Arg, /*DestroyTemps=*/false);
+ Arg = MaybeCreateCXXExprWithTemporaries(Arg);
// Okay: add the default argument to the parameter
Param->setDefaultArg(Arg);
@@ -152,7 +156,6 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
UnparsedDefaultArgLocs.erase(Param);
ExprOwningPtr<Expr> DefaultArg(this, defarg.takeAs<Expr>());
- QualType ParamType = Param->getType();
// Default arguments are only permitted in C++
if (!getLangOptions().CPlusPlus) {
@@ -945,6 +948,51 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
return DeclPtrTy::make(Member);
}
+/// \brief Find the direct and/or virtual base specifiers that
+/// correspond to the given base type, for use in base initialization
+/// within a constructor.
+static bool FindBaseInitializer(Sema &SemaRef,
+ CXXRecordDecl *ClassDecl,
+ QualType BaseType,
+ const CXXBaseSpecifier *&DirectBaseSpec,
+ const CXXBaseSpecifier *&VirtualBaseSpec) {
+ // First, check for a direct base class.
+ DirectBaseSpec = 0;
+ for (CXXRecordDecl::base_class_const_iterator Base
+ = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
+ // We found a direct base of this type. That's what we're
+ // initializing.
+ DirectBaseSpec = &*Base;
+ break;
+ }
+ }
+
+ // Check for a virtual base class.
+ // FIXME: We might be able to short-circuit this if we know in advance that
+ // there are no virtual bases.
+ VirtualBaseSpec = 0;
+ if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
+ // We haven't found a base yet; search the class hierarchy for a
+ // virtual base class.
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl),
+ BaseType, Paths)) {
+ for (CXXBasePaths::paths_iterator Path = Paths.begin();
+ Path != Paths.end(); ++Path) {
+ if (Path->back().Base->isVirtual()) {
+ VirtualBaseSpec = Path->back().Base;
+ break;
+ }
+ }
+ }
+ }
+
+ return DirectBaseSpec || VirtualBaseSpec;
+}
+
/// ActOnMemInitializer - Handle a C++ member initializer.
Sema::MemInitResult
Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
@@ -1000,16 +1048,69 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
}
// It didn't name a member, so see if it names a class.
QualType BaseType;
-
TypeSourceInfo *TInfo = 0;
- if (TemplateTypeTy)
+
+ if (TemplateTypeTy) {
BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
- else
- BaseType = QualType::getFromOpaquePtr(getTypeName(*MemberOrBase, IdLoc,
- S, &SS));
- if (BaseType.isNull())
- return Diag(IdLoc, diag::err_mem_init_not_member_or_class)
- << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+ } else {
+ LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
+ LookupParsedName(R, S, &SS);
+
+ TypeDecl *TyD = R.getAsSingle<TypeDecl>();
+ if (!TyD) {
+ if (R.isAmbiguous()) return true;
+
+ // If no results were found, try to correct typos.
+ if (R.empty() &&
+ CorrectTypo(R, S, &SS, ClassDecl) && R.isSingleResult()) {
+ if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
+ if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) {
+ // We have found a non-static data member with a similar
+ // name to what was typed; complain and initialize that
+ // member.
+ Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+ << MemberOrBase << true << R.getLookupName()
+ << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+
+ return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
+ LParenLoc, RParenLoc);
+ }
+ } else if (TypeDecl *Type = R.getAsSingle<TypeDecl>()) {
+ const CXXBaseSpecifier *DirectBaseSpec;
+ const CXXBaseSpecifier *VirtualBaseSpec;
+ if (FindBaseInitializer(*this, ClassDecl,
+ Context.getTypeDeclType(Type),
+ DirectBaseSpec, VirtualBaseSpec)) {
+ // We have found a direct or virtual base class with a
+ // similar name to what was typed; complain and initialize
+ // that base class.
+ Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+ << MemberOrBase << false << R.getLookupName()
+ << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+
+ TyD = Type;
+ }
+ }
+ }
+
+ if (!TyD) {
+ Diag(IdLoc, diag::err_mem_init_not_member_or_class)
+ << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+ return true;
+ }
+ }
+
+ BaseType = Context.getTypeDeclType(TyD);
+ if (SS.isSet()) {
+ NestedNameSpecifier *Qualifier =
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+ // FIXME: preserve source range information
+ BaseType = Context.getQualifiedNameType(Qualifier, BaseType);
+ }
+ }
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
@@ -1095,14 +1196,13 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
QualType FieldType = Member->getType();
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
+ ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
if (FieldType->isDependentType()) {
// Can't check init for dependent type.
} else if (FieldType->isRecordType()) {
// Member is a record (struct/union/class), so pass the initializer
// arguments down to the record's constructor.
if (!HasDependentArg) {
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
-
C = PerformInitializationByConstructor(FieldType,
MultiExprArg(*this,
(void**)Args,
@@ -1137,7 +1237,8 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
}
else
NewExp = (Expr*)Args[0];
- if (PerformCopyInitialization(NewExp, FieldType, "passing"))
+ if (!Member->isInvalidDecl() &&
+ PerformCopyInitialization(NewExp, FieldType, AA_Passing))
return true;
Args[0] = NewExp;
}
@@ -1174,37 +1275,11 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
// mem-initializer-list can initialize a base class using any
// name that denotes that base class type.
- // First, check for a direct base class.
+ // Check for direct and virtual base classes.
const CXXBaseSpecifier *DirectBaseSpec = 0;
- for (CXXRecordDecl::base_class_const_iterator Base =
- ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) {
- if (Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
- // We found a direct base of this type. That's what we're
- // initializing.
- DirectBaseSpec = &*Base;
- break;
- }
- }
-
- // Check for a virtual base class.
- // FIXME: We might be able to short-circuit this if we know in advance that
- // there are no virtual bases.
const CXXBaseSpecifier *VirtualBaseSpec = 0;
- if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
- // We haven't found a base yet; search the class hierarchy for a
- // virtual base class.
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
- if (IsDerivedFrom(Context.getTypeDeclType(ClassDecl), BaseType, Paths)) {
- for (CXXBasePaths::paths_iterator Path = Paths.begin();
- Path != Paths.end(); ++Path) {
- if (Path->back().Base->isVirtual()) {
- VirtualBaseSpec = Path->back().Base;
- break;
- }
- }
- }
- }
+ FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
+ VirtualBaseSpec);
// C++ [base.class.init]p2:
// If a mem-initializer-id is ambiguous because it designates both
@@ -1224,10 +1299,10 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
}
CXXConstructorDecl *C = 0;
+ ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
if (!BaseType->isDependentType() && !HasDependentArg) {
DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(BaseType).getUnqualifiedType());
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
C = PerformInitializationByConstructor(BaseType,
MultiExprArg(*this,
@@ -1977,6 +2052,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (!Record || Record->isInvalidDecl())
return;
+ if (!Record->isDependentType())
+ AddImplicitlyDeclaredMembersToClass(Record);
+
+ if (Record->isInvalidDecl())
+ return;
+
if (!Record->isAbstract()) {
// Collect all the pure virtual methods and see if this is an abstract
// class after all.
@@ -1987,9 +2068,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (Record->isAbstract())
(void)AbstractClassUsageDiagnoser(*this, Record);
-
- if (!Record->isDependentType() && !Record->isInvalidDecl())
- AddImplicitlyDeclaredMembersToClass(Record);
}
void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
@@ -2261,6 +2339,18 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
}
}
+void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+ if (!RecordD) return;
+ AdjustDeclIfTemplate(RecordD);
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD.getAs<Decl>());
+ PushDeclContext(S, Record);
+}
+
+void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+ if (!RecordD) return;
+ PopDeclContext();
+}
+
/// ActOnStartDelayedCXXMethodDeclaration - We have completed
/// parsing a top-level (non-nested) C++ class, and we are now
/// parsing those parts of the given Method declaration that could
@@ -2270,18 +2360,6 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
/// name. However, it should not bring the parameters into scope;
/// that will be performed by ActOnDelayedCXXMethodParameter.
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
- if (!MethodD)
- return;
-
- AdjustDeclIfTemplate(MethodD);
-
- CXXScopeSpec SS;
- FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
- QualType ClassTy
- = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
- SS.setScopeRep(
- NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
- ActOnCXXEnterDeclaratorScope(S, SS);
}
/// ActOnDelayedCXXMethodParameter - We've already started a delayed
@@ -2318,12 +2396,6 @@ void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
AdjustDeclIfTemplate(MethodD);
FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
- CXXScopeSpec SS;
- QualType ClassTy
- = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
- SS.setScopeRep(
- NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
- ActOnCXXExitDeclaratorScope(S, SS);
// Now that we have our default arguments, check the constructor
// again. It could produce additional diagnostics or affect whether
@@ -2746,6 +2818,28 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
PushOnScopeChains(Namespc, DeclRegionScope);
} else {
// Anonymous namespaces.
+ assert(Namespc->isAnonymousNamespace());
+ CurContext->addDecl(Namespc);
+
+ // Link the anonymous namespace into its parent.
+ NamespaceDecl *PrevDecl;
+ DeclContext *Parent = CurContext->getLookupContext();
+ if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
+ PrevDecl = TU->getAnonymousNamespace();
+ TU->setAnonymousNamespace(Namespc);
+ } else {
+ NamespaceDecl *ND = cast<NamespaceDecl>(Parent);
+ PrevDecl = ND->getAnonymousNamespace();
+ ND->setAnonymousNamespace(Namespc);
+ }
+
+ // Link the anonymous namespace with its previous declaration.
+ if (PrevDecl) {
+ assert(PrevDecl->isAnonymousNamespace());
+ assert(!PrevDecl->getNextNamespace());
+ Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace());
+ PrevDecl->setNextNamespace(Namespc);
+ }
// C++ [namespace.unnamed]p1. An unnamed-namespace-definition
// behaves as if it were replaced by
@@ -2763,20 +2857,19 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// declarations semantically contained within an anonymous
// namespace internal linkage.
- assert(Namespc->isAnonymousNamespace());
- CurContext->addDecl(Namespc);
-
- UsingDirectiveDecl* UD
- = UsingDirectiveDecl::Create(Context, CurContext,
- /* 'using' */ LBrace,
- /* 'namespace' */ SourceLocation(),
- /* qualifier */ SourceRange(),
- /* NNS */ NULL,
- /* identifier */ SourceLocation(),
- Namespc,
- /* Ancestor */ CurContext);
- UD->setImplicit();
- CurContext->addDecl(UD);
+ if (!PrevDecl) {
+ UsingDirectiveDecl* UD
+ = UsingDirectiveDecl::Create(Context, CurContext,
+ /* 'using' */ LBrace,
+ /* 'namespace' */ SourceLocation(),
+ /* qualifier */ SourceRange(),
+ /* NNS */ NULL,
+ /* identifier */ SourceLocation(),
+ Namespc,
+ /* Ancestor */ CurContext);
+ UD->setImplicit();
+ CurContext->addDecl(UD);
+ }
}
// Although we could have an invalid decl (i.e. the namespace name is a
@@ -3696,7 +3789,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *CopyConstructor,
unsigned TypeQuals) {
assert((CopyConstructor->isImplicit() &&
- CopyConstructor->isCopyConstructor(Context, TypeQuals) &&
+ CopyConstructor->isCopyConstructor(TypeQuals) &&
!CopyConstructor->isUsed()) &&
"DefineImplicitCopyConstructor - call it for implicit copy ctor");
@@ -3736,7 +3829,8 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
Sema::OwningExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor,
- MultiExprArg ExprArgs) {
+ MultiExprArg ExprArgs,
+ bool RequiresZeroInit) {
bool Elidable = false;
// C++ [class.copy]p15:
@@ -3747,8 +3841,13 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
// all, even if the class copy constructor or destructor have side effects.
// FIXME: Is this enough?
- if (Constructor->isCopyConstructor(Context)) {
+ if (Constructor->isCopyConstructor()) {
Expr *E = ((Expr **)ExprArgs.get())[0];
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+ if (ICE->getCastKind() == CastExpr::CK_NoOp)
+ E = ICE->getSubExpr();
+ if (CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
+ E = FCE->getSubExpr();
while (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
E = BE->getSubExpr();
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
@@ -3759,10 +3858,12 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
Elidable = !CE->getCallReturnType()->isReferenceType();
else if (isa<CXXTemporaryObjectExpr>(E))
Elidable = true;
+ else if (isa<CXXConstructExpr>(E))
+ Elidable = true;
}
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
- Elidable, move(ExprArgs));
+ Elidable, move(ExprArgs), RequiresZeroInit);
}
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
@@ -3770,13 +3871,15 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
Sema::OwningExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, bool Elidable,
- MultiExprArg ExprArgs) {
+ MultiExprArg ExprArgs,
+ bool RequiresZeroInit) {
unsigned NumExprs = ExprArgs.size();
Expr **Exprs = (Expr **)ExprArgs.release();
MarkDeclarationReferenced(ConstructLoc, Constructor);
- return Owned(CXXConstructExpr::Create(Context, DeclInitType, Constructor,
- Elidable, Exprs, NumExprs));
+ return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
+ Constructor, Elidable, Exprs, NumExprs,
+ RequiresZeroInit));
}
Sema::OwningExprResult
@@ -3806,7 +3909,7 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD,
Expr *Temp = TempResult.takeAs<Expr>();
MarkDeclarationReferenced(VD->getLocation(), Constructor);
- Temp = MaybeCreateCXXExprWithTemporaries(Temp, /*DestroyTemps=*/true);
+ Temp = MaybeCreateCXXExprWithTemporaries(Temp);
VD->setInit(Context, Temp);
return false;
@@ -3829,8 +3932,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
MultiExprArg Exprs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
- unsigned NumExprs = Exprs.size();
- assert(NumExprs != 0 && Exprs.get() && "missing expressions");
+ assert(Exprs.size() != 0 && Exprs.get() && "missing expressions");
Decl *RealDecl = Dcl.getAs<Decl>();
// If there is no declaration, there was an error parsing it. Just ignore
@@ -3881,53 +3983,50 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
DeclInitType = Context.getBaseElementType(Array);
- // FIXME: This isn't the right place to complete the type.
if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
diag::err_typecheck_decl_incomplete_type)) {
VDecl->setInvalidDecl();
return;
}
- if (VDecl->getType()->isRecordType()) {
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
-
- CXXConstructorDecl *Constructor
- = PerformInitializationByConstructor(DeclInitType,
- move(Exprs),
- VDecl->getLocation(),
- SourceRange(VDecl->getLocation(),
- RParenLoc),
- VDecl->getDeclName(),
- InitializationKind::CreateDirect(VDecl->getLocation(),
- LParenLoc,
- RParenLoc),
- ConstructorArgs);
- if (!Constructor)
- RealDecl->setInvalidDecl();
- else {
- VDecl->setCXXDirectInitializer(true);
- if (InitializeVarWithConstructor(VDecl, Constructor,
- move_arg(ConstructorArgs)))
- RealDecl->setInvalidDecl();
- FinalizeVarWithDestructor(VDecl, DeclInitType);
- }
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ VDecl->setInvalidDecl();
+
+ const VarDecl *Def = 0;
+ if (VDecl->getDefinition(Def)) {
+ Diag(VDecl->getLocation(), diag::err_redefinition)
+ << VDecl->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ VDecl->setInvalidDecl();
return;
}
-
- if (NumExprs > 1) {
- Diag(CommaLocs[0], diag::err_builtin_direct_init_more_than_one_arg)
- << SourceRange(VDecl->getLocation(), RParenLoc);
- RealDecl->setInvalidDecl();
+
+ // Capture the variable that is being initialized and the style of
+ // initialization.
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
+
+ // FIXME: Poor source location information.
+ InitializationKind Kind
+ = InitializationKind::CreateDirect(VDecl->getLocation(),
+ LParenLoc, RParenLoc);
+
+ InitializationSequence InitSeq(*this, Entity, Kind,
+ (Expr**)Exprs.get(), Exprs.size());
+ OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs));
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
return;
}
-
- // Let clients know that initialization was done with a direct initializer.
+
+ Result = MaybeCreateCXXExprWithTemporaries(move(Result));
+ VDecl->setInit(Context, Result.takeAs<Expr>());
VDecl->setCXXDirectInitializer(true);
- assert(NumExprs == 1 && "Expected 1 expression");
- // Set the init expression, handles conversions.
- AddInitializerToDecl(Dcl, ExprArg(*this, Exprs.release()[0]),
- /*DirectInit=*/true);
+ if (VDecl->getType()->getAs<RecordType>())
+ FinalizeVarWithDestructor(VDecl, DeclInitType);
}
/// \brief Add the applicable constructor candidates for an initialization
@@ -4164,7 +4263,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
/// type, and the first type (T1) is the pointee type of the reference
/// type being initialized.
Sema::ReferenceCompareResult
-Sema::CompareReferenceRelationship(SourceLocation Loc,
+Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType OrigT1, QualType OrigT2,
bool& DerivedToBase) {
assert(!OrigT1->isReferenceType() &&
@@ -4173,8 +4272,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType T1 = Context.getCanonicalType(OrigT1);
QualType T2 = Context.getCanonicalType(OrigT2);
- QualType UnqualT1 = T1.getLocalUnqualifiedType();
- QualType UnqualT2 = T2.getLocalUnqualifiedType();
+ Qualifiers T1Quals, T2Quals;
+ QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+ QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
// C++ [dcl.init.ref]p4:
// Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
@@ -4192,6 +4292,13 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
// At this point, we know that T1 and T2 are reference-related (at
// least).
+ // If the type is an array type, promote the element qualifiers to the type
+ // for comparison.
+ if (isa<ArrayType>(T1) && T1Quals)
+ T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+ if (isa<ArrayType>(T2) && T2Quals)
+ T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+
// C++ [dcl.init.ref]p4:
// "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
// reference-related to T2 and cv1 is the same cv-qualification
@@ -4199,7 +4306,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
// overload resolution, cases for which cv1 is greater
// cv-qualification than cv2 are identified as
// reference-compatible with added qualification (see 13.3.3.2).
- if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
+ if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers())
return Ref_Compatible;
else if (T1.isMoreQualifiedThan(T2))
return Ref_Compatible_With_Added_Qualification;
@@ -4462,7 +4569,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) {
if (!ICS)
Diag(DeclLoc, diag::err_not_reference_to_const_init)
- << T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value")
+ << T1 << int(InitLvalue != Expr::LV_Valid)
<< T2 << Init->getSourceRange();
return true;
}
@@ -4528,7 +4635,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// initialization fails.
if (!ICS)
Diag(DeclLoc, diag::err_reference_init_drops_quals)
- << T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value")
+ << T1 << int(InitLvalue != Expr::LV_Valid)
<< T2 << Init->getSourceRange();
return true;
}
@@ -4542,7 +4649,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
(T1->isRecordType() || T2->isRecordType())) {
if (!ICS)
Diag(DeclLoc, diag::err_typecheck_convert_incompatible)
- << DeclType << Init->getType() << "initializing" << Init->getSourceRange();
+ << DeclType << Init->getType() << AA_Initializing << Init->getSourceRange();
return true;
}
@@ -4576,7 +4683,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
return ICS->ConversionKind == ImplicitConversionSequence::BadConversion;
} else {
ImplicitConversionSequence Conversions;
- bool badConversion = PerformImplicitConversion(Init, T1, "initializing",
+ bool badConversion = PerformImplicitConversion(Init, T1, AA_Initializing,
false, false,
Conversions);
if (badConversion) {
@@ -4664,7 +4771,7 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
<< FnDecl->getDeclName() << ExpectedFirstParamType;
// Check that the first parameter type is what we expect.
- if (SemaRef.Context.getCanonicalType(FirstParamType) !=
+ if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
ExpectedFirstParamType)
return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
<< FnDecl->getDeclName() << ExpectedFirstParamType;
@@ -5154,13 +5261,10 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
// C++98 [class.friend]p1: A friend of a class is a function
// or class that is not a member of the class . . .
- // But that's a silly restriction which nobody implements for
- // inner classes, and C++0x removes it anyway, so we only report
- // this (as a warning) if we're being pedantic.
- if (!getLangOptions().CPlusPlus0x)
- if (const RecordType *RT = T->getAs<RecordType>())
- if (RT->getDecl()->getDeclContext() == CurContext)
- Diag(DS.getFriendSpecLoc(), diag::ext_friend_inner_class);
+ // This is fixed in DR77, which just barely didn't make the C++03
+ // deadline. It's also a very silly restriction that seriously
+ // affects inner classes and which nobody else seems to implement;
+ // thus we never diagnose it, not even in -pedantic.
Decl *D;
if (TempParams.size())
@@ -5341,6 +5445,9 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
FrD->setAccess(AS_public);
CurContext->addDecl(FrD);
+ if (D.getName().getKind() == UnqualifiedId::IK_TemplateId)
+ FrD->setSpecialization(true);
+
return DeclPtrTy::make(ND);
}
@@ -5421,6 +5528,18 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
return true;
}
+ // C++ [class.virtual]p6:
+ // If the return type of D::f differs from the return type of B::f, the
+ // class type in the return type of D::f shall be complete at the point of
+ // declaration of D::f or shall be the class type D.
+ if (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
+ if (!RT->isBeingDefined() &&
+ RequireCompleteType(New->getLocation(), NewClassTy,
+ PDiag(diag::err_covariant_return_incomplete)
+ << New->getDeclName()))
+ return true;
+ }
+
if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
// Check if the new class derives from the old class.
if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
@@ -5497,50 +5616,32 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
return true;
}
-/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
-/// initializer for the declaration 'Dcl'.
+/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
+/// an initializer for the out-of-line declaration 'Dcl'. The scope
+/// is a fresh scope pushed for just this purpose.
+///
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
/// static data member of class X, names should be looked up in the scope of
/// class X.
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
- AdjustDeclIfTemplate(Dcl);
-
- Decl *D = Dcl.getAs<Decl>();
// If there is no declaration, there was an error parsing it.
- if (D == 0)
- return;
-
- // Check whether it is a declaration with a nested name specifier like
- // int foo::bar;
- if (!D->isOutOfLine())
- return;
-
- // C++ [basic.lookup.unqual]p13
- //
- // A name used in the definition of a static data member of class X
- // (after the qualified-id of the static member) is looked up as if the name
- // was used in a member function of X.
+ Decl *D = Dcl.getAs<Decl>();
+ if (D == 0) return;
- // Change current context into the context of the initializing declaration.
+ // We should only get called for declarations with scope specifiers, like:
+ // int foo::bar;
+ assert(D->isOutOfLine());
EnterDeclaratorContext(S, D->getDeclContext());
}
/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
-/// initializer for the declaration 'Dcl'.
+/// initializer for the out-of-line declaration 'Dcl'.
void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
- AdjustDeclIfTemplate(Dcl);
-
- Decl *D = Dcl.getAs<Decl>();
// If there is no declaration, there was an error parsing it.
- if (D == 0)
- return;
-
- // Check whether it is a declaration with a nested name specifier like
- // int foo::bar;
- if (!D->isOutOfLine())
- return;
+ Decl *D = Dcl.getAs<Decl>();
+ if (D == 0) return;
- assert(S->getEntity() == D->getDeclContext() && "Context imbalance!");
+ assert(D->isOutOfLine());
ExitDeclaratorContext(S);
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index a768e1b..beadb58 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1950,6 +1950,10 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
!(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
!(Attributes & ObjCDeclSpec::DQ_PR_copy)));
QualType T = GetTypeForDeclarator(FD.D, S);
+ if (T->isReferenceType()) {
+ Diag(AtLoc, diag::error_reference_property);
+ return DeclPtrTy();
+ }
Decl *ClassDecl = ClassCategory.getAs<Decl>();
ObjCInterfaceDecl *CCPrimary = 0; // continuation class's primary class
// May modify Attributes.
@@ -2028,7 +2032,14 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
FD.D.getIdentifierLoc(),
FD.D.getIdentifier(), T);
- DC->addDecl(PDecl);
+ DeclContext::lookup_result Found = DC->lookup(PDecl->getDeclName());
+ if (Found.first != Found.second && isa<ObjCPropertyDecl>(*Found.first)) {
+ Diag(PDecl->getLocation(), diag::err_duplicate_property);
+ Diag((*Found.first)->getLocation(), diag::note_property_declare);
+ PDecl->setInvalidDecl();
+ }
+ else
+ DC->addDecl(PDecl);
if (T->isArrayType() || T->isFunctionType()) {
Diag(AtLoc, diag::err_property_type) << T;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 358f445..7bf04d8 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -258,44 +259,17 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) {
bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) {
DefaultArgumentPromotion(Expr);
- if (Expr->getType()->isObjCInterfaceType()) {
- switch (ExprEvalContexts.back().Context ) {
- case Unevaluated:
- // The argument will never be evaluated, so don't complain.
- break;
-
- case PotentiallyEvaluated:
- Diag(Expr->getLocStart(),
- diag::err_cannot_pass_objc_interface_to_vararg)
- << Expr->getType() << CT;
- return true;
-
- case PotentiallyPotentiallyEvaluated:
- ExprEvalContexts.back().addDiagnostic(Expr->getLocStart(),
- PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
- << Expr->getType() << CT);
- break;
- }
- }
-
- if (!Expr->getType()->isPODType()) {
- switch (ExprEvalContexts.back().Context ) {
- case Unevaluated:
- // The argument will never be evaluated, so don't complain.
- break;
-
- case PotentiallyEvaluated:
- Diag(Expr->getLocStart(), diag::warn_cannot_pass_non_pod_arg_to_vararg)
- << Expr->getType() << CT;
- break;
+ if (Expr->getType()->isObjCInterfaceType() &&
+ DiagRuntimeBehavior(Expr->getLocStart(),
+ PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
+ << Expr->getType() << CT))
+ return true;
- case PotentiallyPotentiallyEvaluated:
- ExprEvalContexts.back().addDiagnostic(Expr->getLocStart(),
- PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
- << Expr->getType() << CT);
- break;
- }
- }
+ if (!Expr->getType()->isPODType() &&
+ DiagRuntimeBehavior(Expr->getLocStart(),
+ PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
+ << Expr->getType() << CT))
+ return true;
return false;
}
@@ -590,7 +564,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
== Context.getCanonicalType(ThisType)) ||
IsDerivedFrom(ThisType, AnonFieldType)) {
// Our base object expression is "this".
- BaseObjectExpr = new (Context) CXXThisExpr(SourceLocation(),
+ BaseObjectExpr = new (Context) CXXThisExpr(Loc,
MD->getThisType(Context));
BaseObjectIsPointer = true;
}
@@ -761,23 +735,9 @@ static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
return true;
}
-/// Determines if this a C++ class member.
-static bool IsClassMember(NamedDecl *D) {
- DeclContext *DC = D->getDeclContext();
-
- // C++0x [class.mem]p1:
- // The enumerators of an unscoped enumeration defined in
- // the class are members of the class.
- // FIXME: support C++0x scoped enumerations.
- if (isa<EnumDecl>(DC))
- DC = DC->getParent();
-
- return DC->isRecord();
-}
-
/// Determines if this is an instance member of a class.
static bool IsInstanceMember(NamedDecl *D) {
- assert(IsClassMember(D) &&
+ assert(D->isCXXClassMember() &&
"checking whether non-member is instance member");
if (isa<FieldDecl>(D)) return true;
@@ -839,7 +799,7 @@ enum IMAKind {
/// not be caught until template-instantiation.
static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
const LookupResult &R) {
- assert(!R.empty() && IsClassMember(*R.begin()));
+ assert(!R.empty() && (*R.begin())->isCXXClassMember());
bool isStaticContext =
(!isa<CXXMethodDecl>(SemaRef.CurContext) ||
@@ -916,6 +876,112 @@ static void DiagnoseInstanceReference(Sema &SemaRef,
SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range;
}
+/// Diagnose an empty lookup.
+///
+/// \return false if new lookup candidates were found
+bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS,
+ LookupResult &R) {
+ DeclarationName Name = R.getLookupName();
+
+ unsigned diagnostic = diag::err_undeclared_var_use;
+ unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest;
+ if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
+ Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+ diagnostic = diag::err_undeclared_use;
+ diagnostic_suggest = diag::err_undeclared_use_suggest;
+ }
+
+ // If the original lookup was an unqualified lookup, fake an
+ // unqualified lookup. This is useful when (for example) the
+ // original lookup would not have found something because it was a
+ // dependent name.
+ for (DeclContext *DC = SS.isEmpty()? CurContext : 0;
+ DC; DC = DC->getParent()) {
+ if (isa<CXXRecordDecl>(DC)) {
+ LookupQualifiedName(R, DC);
+
+ if (!R.empty()) {
+ // Don't give errors about ambiguities in this lookup.
+ R.suppressDiagnostics();
+
+ CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
+ bool isInstance = CurMethod &&
+ CurMethod->isInstance() &&
+ DC == CurMethod->getParent();
+
+ // Give a code modification hint to insert 'this->'.
+ // TODO: fixit for inserting 'Base<T>::' in the other cases.
+ // Actually quite difficult!
+ if (isInstance)
+ Diag(R.getNameLoc(), diagnostic) << Name
+ << CodeModificationHint::CreateInsertion(R.getNameLoc(),
+ "this->");
+ else
+ Diag(R.getNameLoc(), diagnostic) << Name;
+
+ // Do we really want to note all of these?
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ Diag((*I)->getLocation(), diag::note_dependent_var_use);
+
+ // Tell the callee to try to recover.
+ return false;
+ }
+ }
+ }
+
+ // We didn't find anything, so try to correct for a typo.
+ if (S && CorrectTypo(R, S, &SS)) {
+ if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) {
+ if (SS.isEmpty())
+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName()
+ << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+ else
+ Diag(R.getNameLoc(), diag::err_no_member_suggest)
+ << Name << computeDeclContext(SS, false) << R.getLookupName()
+ << SS.getRange()
+ << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+
+ // Tell the callee to try to recover.
+ return false;
+ }
+
+ if (isa<TypeDecl>(*R.begin()) || isa<ObjCInterfaceDecl>(*R.begin())) {
+ // FIXME: If we ended up with a typo for a type name or
+ // Objective-C class name, we're in trouble because the parser
+ // is in the wrong place to recover. Suggest the typo
+ // correction, but don't make it a fix-it since we're not going
+ // to recover well anyway.
+ if (SS.isEmpty())
+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName();
+ else
+ Diag(R.getNameLoc(), diag::err_no_member_suggest)
+ << Name << computeDeclContext(SS, false) << R.getLookupName()
+ << SS.getRange();
+
+ // Don't try to recover; it won't work.
+ return true;
+ }
+
+ R.clear();
+ }
+
+ // Emit a special diagnostic for failed member lookups.
+ // FIXME: computing the declaration context might fail here (?)
+ if (!SS.isEmpty()) {
+ Diag(R.getNameLoc(), diag::err_no_member)
+ << Name << computeDeclContext(SS, false)
+ << SS.getRange();
+ return true;
+ }
+
+ // Give up, we can't recover.
+ Diag(R.getNameLoc(), diagnostic) << Name;
+ return true;
+}
+
Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
const CXXScopeSpec &SS,
UnqualifiedId &Id,
@@ -988,17 +1054,11 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
if (R.empty()) {
- if (!SS.isEmpty())
- return ExprError(Diag(NameLoc, diag::err_no_member)
- << Name << computeDeclContext(SS, false)
- << SS.getRange());
- else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
- Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
- Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
- return ExprError(Diag(NameLoc, diag::err_undeclared_use)
- << Name);
- else
- return ExprError(Diag(NameLoc, diag::err_undeclared_var_use) << Name);
+ if (DiagnoseEmptyLookup(S, SS, R))
+ return ExprError();
+
+ assert(!R.empty() &&
+ "DiagnoseEmptyLookup returned false but added no results");
}
}
@@ -1051,35 +1111,10 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
// class member access expression.
// But note that &SomeClass::foo is grammatically distinct, even
// though we don't parse it that way.
- if (!R.empty() && IsClassMember(*R.begin())) {
+ if (!R.empty() && (*R.begin())->isCXXClassMember()) {
bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty());
-
- if (!isAbstractMemberPointer) {
- switch (ClassifyImplicitMemberAccess(*this, R)) {
- case IMA_Instance:
- return BuildImplicitMemberExpr(SS, R, TemplateArgs, true);
-
- case IMA_AnonymousMember:
- assert(R.isSingleResult());
- return BuildAnonymousStructUnionMemberReference(R.getNameLoc(),
- R.getAsSingle<FieldDecl>());
-
- case IMA_Mixed:
- case IMA_Mixed_Unrelated:
- case IMA_Unresolved:
- return BuildImplicitMemberExpr(SS, R, TemplateArgs, false);
-
- case IMA_Static:
- case IMA_Mixed_StaticContext:
- case IMA_Unresolved_StaticContext:
- break;
-
- case IMA_Error_StaticContext:
- case IMA_Error_Unrelated:
- DiagnoseInstanceReference(*this, SS, R);
- return ExprError();
- }
- }
+ if (!isAbstractMemberPointer)
+ return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs);
}
if (TemplateArgs)
@@ -1088,6 +1123,42 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
return BuildDeclarationNameExpr(SS, R, ADL);
}
+/// Builds an expression which might be an implicit member expression.
+Sema::OwningExprResult
+Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ switch (ClassifyImplicitMemberAccess(*this, R)) {
+ case IMA_Instance:
+ return BuildImplicitMemberExpr(SS, R, TemplateArgs, true);
+
+ case IMA_AnonymousMember:
+ assert(R.isSingleResult());
+ return BuildAnonymousStructUnionMemberReference(R.getNameLoc(),
+ R.getAsSingle<FieldDecl>());
+
+ case IMA_Mixed:
+ case IMA_Mixed_Unrelated:
+ case IMA_Unresolved:
+ return BuildImplicitMemberExpr(SS, R, TemplateArgs, false);
+
+ case IMA_Static:
+ case IMA_Mixed_StaticContext:
+ case IMA_Unresolved_StaticContext:
+ if (TemplateArgs)
+ return BuildTemplateIdExpr(SS, R, false, *TemplateArgs);
+ return BuildDeclarationNameExpr(SS, R, false);
+
+ case IMA_Error_StaticContext:
+ case IMA_Error_Unrelated:
+ DiagnoseInstanceReference(*this, SS, R);
+ return ExprError();
+ }
+
+ llvm_unreachable("unexpected instance member access kind");
+ return ExprError();
+}
+
/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
/// declaration name, generally during template instantiation.
/// There's a large number of things which don't need to be done along
@@ -1315,7 +1386,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
// -- a declaration of a class member
// Since using decls preserve this property, we check this on the
// original decl.
- if (IsClassMember(D))
+ if (D->isCXXClassMember())
return false;
// C++0x [basic.lookup.argdep]p3:
@@ -1408,7 +1479,6 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
assert(D && "Cannot refer to a NULL declaration");
assert(!isa<FunctionTemplateDecl>(D) &&
"Cannot refer unambiguously to a function template");
- DeclarationName Name = D->getDeclName();
if (CheckDeclInExpr(*this, Loc, D))
return ExprError();
@@ -1427,7 +1497,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
if (!VD) {
Diag(Loc, diag::err_ref_non_value)
<< D << SS.getRange();
- Diag(D->getLocation(), diag::note_previous_declaration);
+ Diag(D->getLocation(), diag::note_declared_at);
return ExprError();
}
@@ -1515,11 +1585,17 @@ Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
if (Literal.hadError())
return ExprError();
- QualType type = getLangOptions().CPlusPlus ? Context.CharTy : Context.IntTy;
+ QualType Ty;
+ if (!getLangOptions().CPlusPlus)
+ Ty = Context.IntTy; // 'x' and L'x' -> int in C.
+ else if (Literal.isWide())
+ Ty = Context.WCharTy; // L'x' -> wchar_t in C++.
+ else
+ Ty = Context.CharTy; // 'x' -> char in C++
return Owned(new (Context) CharacterLiteral(Literal.getValue(),
Literal.isWide(),
- type, Tok.getLocation()));
+ Ty, Tok.getLocation()));
}
Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) {
@@ -1558,9 +1634,31 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) {
const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty);
- // isExact will be set by GetFloatValue().
- bool isExact = false;
- llvm::APFloat Val = Literal.GetFloatValue(Format, &isExact);
+ using llvm::APFloat;
+ APFloat Val(Format);
+
+ APFloat::opStatus result = Literal.GetFloatValue(Val);
+
+ // Overflow is always an error, but underflow is only an error if
+ // we underflowed to zero (APFloat reports denormals as underflow).
+ if ((result & APFloat::opOverflow) ||
+ ((result & APFloat::opUnderflow) && Val.isZero())) {
+ unsigned diagnostic;
+ llvm::SmallVector<char, 20> buffer;
+ if (result & APFloat::opOverflow) {
+ diagnostic = diag::err_float_overflow;
+ APFloat::getLargest(Format).toString(buffer);
+ } else {
+ diagnostic = diag::err_float_underflow;
+ APFloat::getSmallest(Format).toString(buffer);
+ }
+
+ Diag(Tok.getLocation(), diagnostic)
+ << Ty
+ << llvm::StringRef(buffer.data(), buffer.size());
+ }
+
+ bool isExact = (result == APFloat::opOK);
Res = new (Context) FloatingLiteral(Val, isExact, Ty, Tok.getLocation());
} else if (!Literal.isIntegerLiteral()) {
@@ -1698,9 +1796,8 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
}
if (RequireCompleteType(OpLoc, exprType,
- isSizeof ? diag::err_sizeof_incomplete_type :
- PDiag(diag::err_alignof_incomplete_type)
- << ExprRange))
+ PDiag(diag::err_sizeof_alignof_incomplete_type)
+ << int(!isSizeof) << ExprRange))
return true;
// Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
@@ -2054,20 +2151,12 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
}
}
- // If this is a halving swizzle, verify that the base type has an even
- // number of elements.
- if (HalvingSwizzle && (vecType->getNumElements() & 1U)) {
- Diag(OpLoc, diag::err_ext_vector_component_requires_even)
- << baseType << SourceRange(CompLoc);
- return QualType();
- }
-
// The component accessor looks fine - now we need to compute the actual type.
// The vector type is implied by the component accessor. For example,
// vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
// vec4.s0 is a float, vec4.s23 is a vec3, etc.
// vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
- unsigned CompSize = HalvingSwizzle ? vecType->getNumElements() / 2
+ unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2
: CompName->getLength();
if (HexSwizzle)
CompSize--;
@@ -2277,6 +2366,23 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
// The record definition is complete, now look up the member.
SemaRef.LookupQualifiedName(R, DC);
+ if (!R.empty())
+ return false;
+
+ // We didn't find anything with the given name, so try to correct
+ // for typos.
+ DeclarationName Name = R.getLookupName();
+ if (SemaRef.CorrectTypo(R, 0, &SS, DC) &&
+ (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) {
+ SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
+ << Name << DC << R.getLookupName() << SS.getRange()
+ << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+ return false;
+ } else {
+ R.clear();
+ }
+
return false;
}
@@ -2372,6 +2478,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
// result.
if (R.isOverloadedResult() || R.isUnresolvableResult()) {
bool Dependent =
+ BaseExprType->isDependentType() ||
R.isUnresolvableResult() ||
UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs);
@@ -3059,28 +3166,36 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
if (Result.isInvalid())
return ExprError();
- if (SetParamDefaultArgument(Param, move(Result),
- /*FIXME:EqualLoc*/
- UninstExpr->getSourceRange().getBegin()))
+ // Check the expression as an initializer for the parameter.
+ InitializedEntity Entity
+ = InitializedEntity::InitializeParameter(Param);
+ InitializationKind Kind
+ = InitializationKind::CreateCopy(Param->getLocation(),
+ /*FIXME:EqualLoc*/UninstExpr->getSourceRange().getBegin());
+ Expr *ResultE = Result.takeAs<Expr>();
+
+ InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1);
+ Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, (void**)&ResultE, 1));
+ if (Result.isInvalid())
return ExprError();
+
+ // Build the default argument expression.
+ return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param,
+ Result.takeAs<Expr>()));
}
- Expr *DefaultExpr = Param->getDefaultArg();
-
// If the default expression creates temporaries, we need to
// push them to the current stack of expression temporaries so they'll
// be properly destroyed.
- if (CXXExprWithTemporaries *E
- = dyn_cast_or_null<CXXExprWithTemporaries>(DefaultExpr)) {
- assert(!E->shouldDestroyTemporaries() &&
- "Can't destroy temporaries in a default argument expr!");
- for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I)
- ExprTemporaries.push_back(E->getTemporary(I));
- }
+ // FIXME: We should really be rebuilding the default argument with new
+ // bound temporaries; see the comment in PR5810.
+ for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i)
+ ExprTemporaries.push_back(Param->getDefaultArgTemporary(i));
}
// We already type-checked the argument, so we know it works.
- return Owned(CXXDefaultArgExpr::Create(Context, Param));
+ return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param));
}
/// ConvertArgumentsForCall - Converts the arguments specified in
@@ -3169,12 +3284,22 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
<< Arg->getSourceRange()))
return true;
- // Pass the argument.
- if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
- return true;
+ // Pass the argument
+ ParmVarDecl *Param = 0;
+ if (FDecl && i < FDecl->getNumParams())
+ Param = FDecl->getParamDecl(i);
+
- if (!ProtoArgType->isReferenceType())
- Arg = MaybeBindToTemporary(Arg).takeAs<Expr>();
+ InitializedEntity Entity =
+ Param? InitializedEntity::InitializeParameter(Param)
+ : InitializedEntity::InitializeParameter(ProtoArgType);
+ OwningExprResult ArgE = PerformCopyInitialization(Entity,
+ SourceLocation(),
+ Owned(Arg));
+ if (ArgE.isInvalid())
+ return true;
+
+ Arg = ArgE.takeAs<Expr>();
} else {
ParmVarDecl *Param = FDecl->getParamDecl(i);
@@ -3200,64 +3325,6 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
return Invalid;
}
-/// \brief "Deconstruct" the function argument of a call expression to find
-/// the underlying declaration (if any), the name of the called function,
-/// whether argument-dependent lookup is available, whether it has explicit
-/// template arguments, etc.
-void Sema::DeconstructCallFunction(Expr *FnExpr,
- llvm::SmallVectorImpl<NamedDecl*> &Fns,
- DeclarationName &Name,
- NestedNameSpecifier *&Qualifier,
- SourceRange &QualifierRange,
- bool &ArgumentDependentLookup,
- bool &Overloaded,
- bool &HasExplicitTemplateArguments,
- TemplateArgumentListInfo &ExplicitTemplateArgs) {
- // Set defaults for all of the output parameters.
- Name = DeclarationName();
- Qualifier = 0;
- QualifierRange = SourceRange();
- ArgumentDependentLookup = false;
- Overloaded = false;
- HasExplicitTemplateArguments = false;
-
- // If we're directly calling a function, get the appropriate declaration.
- // Also, in C++, keep track of whether we should perform argument-dependent
- // lookup and whether there were any explicitly-specified template arguments.
- while (true) {
- if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr))
- FnExpr = IcExpr->getSubExpr();
- else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) {
- FnExpr = PExpr->getSubExpr();
- } else if (isa<UnaryOperator>(FnExpr) &&
- cast<UnaryOperator>(FnExpr)->getOpcode()
- == UnaryOperator::AddrOf) {
- FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr();
- } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) {
- Fns.push_back(cast<NamedDecl>(DRExpr->getDecl()));
- ArgumentDependentLookup = false;
- if ((Qualifier = DRExpr->getQualifier()))
- QualifierRange = DRExpr->getQualifierRange();
- break;
- } else if (UnresolvedLookupExpr *UnresLookup
- = dyn_cast<UnresolvedLookupExpr>(FnExpr)) {
- Name = UnresLookup->getName();
- Fns.append(UnresLookup->decls_begin(), UnresLookup->decls_end());
- ArgumentDependentLookup = UnresLookup->requiresADL();
- Overloaded = UnresLookup->isOverloaded();
- if ((Qualifier = UnresLookup->getQualifier()))
- QualifierRange = UnresLookup->getQualifierRange();
- if (UnresLookup->hasExplicitTemplateArgs()) {
- HasExplicitTemplateArguments = true;
- UnresLookup->copyTemplateArgumentsInto(ExplicitTemplateArgs);
- }
- break;
- } else {
- break;
- }
- }
-}
-
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
@@ -3372,72 +3439,23 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
// If we're directly calling a function, get the appropriate declaration.
// Also, in C++, keep track of whether we should perform argument-dependent
// lookup and whether there were any explicitly-specified template arguments.
- llvm::SmallVector<NamedDecl*,8> Fns;
- DeclarationName UnqualifiedName;
- bool Overloaded;
- bool ADL;
- bool HasExplicitTemplateArgs = 0;
- TemplateArgumentListInfo ExplicitTemplateArgs;
- NestedNameSpecifier *Qualifier = 0;
- SourceRange QualifierRange;
- DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange,
- ADL, Overloaded, HasExplicitTemplateArgs,
- ExplicitTemplateArgs);
-
- NamedDecl *NDecl; // the specific declaration we're calling, if applicable
- FunctionDecl *FDecl; // same, if it's known to be a function
-
- if (Overloaded || ADL) {
-#ifndef NDEBUG
- if (ADL) {
- // To do ADL, we must have found an unqualified name.
- assert(UnqualifiedName && "found no unqualified name for ADL");
-
- // We don't perform ADL for implicit declarations of builtins.
- // Verify that this was correctly set up.
- if (Fns.size() == 1 && (FDecl = dyn_cast<FunctionDecl>(Fns[0])) &&
- FDecl->getBuiltinID() && FDecl->isImplicit())
- assert(0 && "performing ADL for builtin");
-
- // We don't perform ADL in C.
- assert(getLangOptions().CPlusPlus && "ADL enabled in C");
- }
-
- if (Overloaded) {
- // To be overloaded, we must either have multiple functions or
- // at least one function template (which is effectively an
- // infinite set of functions).
- assert((Fns.size() > 1 ||
- (Fns.size() == 1 &&
- isa<FunctionTemplateDecl>(Fns[0]->getUnderlyingDecl())))
- && "unrecognized overload situation");
- }
-#endif
-
- FDecl = ResolveOverloadedCallFn(Fn, Fns, UnqualifiedName,
- (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0),
- LParenLoc, Args, NumArgs, CommaLocs,
- RParenLoc, ADL);
- if (!FDecl)
- return ExprError();
-
- Fn = FixOverloadedFunctionReference(Fn, FDecl);
- NDecl = FDecl;
- } else {
- assert(Fns.size() <= 1 && "overloaded without Overloaded flag");
- if (Fns.empty())
- NDecl = 0;
- else {
- NDecl = Fns[0];
- }
+ Expr *NakedFn = Fn->IgnoreParens();
+ if (isa<UnresolvedLookupExpr>(NakedFn)) {
+ UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
+ return BuildOverloadedCallExpr(Fn, ULE, LParenLoc, Args, NumArgs,
+ CommaLocs, RParenLoc);
}
+ NamedDecl *NDecl = 0;
+ if (isa<DeclRefExpr>(NakedFn))
+ NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
+
return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc);
}
-/// BuildCallExpr - Build a call to a resolved expression, i.e. an
-/// expression not of \p OverloadTy. The expression should
+/// BuildResolvedCallExpr - Build a call to a resolved expression,
+/// i.e. an expression not of \p OverloadTy. The expression should
/// unary-convert to an expression of function-pointer or
/// block-pointer type.
///
@@ -3547,8 +3565,9 @@ Action::OwningExprResult
Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc, ExprArg InitExpr) {
assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
- //FIXME: Preserve type source info.
- QualType literalType = GetTypeFromParser(Ty);
+
+ QualType literalType = GetTypeFromParser(Ty);
+
// FIXME: put back this assert when initializers are worked out.
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
Expr *literalExpr = static_cast<Expr*>(InitExpr.get());
@@ -3564,16 +3583,29 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
literalExpr->getSourceRange().getEnd())))
return ExprError();
- if (CheckInitializerTypes(literalExpr, literalType, LParenLoc,
- DeclarationName(), /*FIXME:DirectInit=*/false))
+ InitializedEntity Entity
+ = InitializedEntity::InitializeTemporary(literalType);
+ InitializationKind Kind
+ = InitializationKind::CreateCast(SourceRange(LParenLoc, RParenLoc),
+ /*IsCStyleCast=*/true);
+ InitializationSequence InitSeq(*this, Entity, Kind, &literalExpr, 1);
+ OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, (void**)&literalExpr, 1),
+ &literalType);
+ if (Result.isInvalid())
return ExprError();
+ InitExpr.release();
+ literalExpr = static_cast<Expr*>(Result.get());
bool isFileScope = getCurFunctionOrMethodDecl() == 0;
if (isFileScope) { // 6.5.2.5p3
if (CheckForConstantInitializer(literalExpr, literalType))
return ExprError();
}
- InitExpr.release();
+
+ Result.release();
+
+ // FIXME: Store the TInfo to preserve type information better.
return Owned(new (Context) CompoundLiteralExpr(LParenLoc, literalType,
literalExpr, isFileScope));
}
@@ -3600,7 +3632,9 @@ static CastExpr::CastKind getScalarCastKind(ASTContext &Context,
if (SrcTy->hasPointerRepresentation()) {
if (DestTy->hasPointerRepresentation())
- return CastExpr::CK_BitCast;
+ return DestTy->isObjCObjectPointerType() ?
+ CastExpr::CK_AnyPointerToObjCPointerCast :
+ CastExpr::CK_BitCast;
if (DestTy->isIntegerType())
return CastExpr::CK_PointerToIntegral;
}
@@ -4632,7 +4666,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// expression is implicitly converted (C++ 4) to the
// cv-unqualified type of the left operand.
if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType(),
- "assigning"))
+ AA_Assigning))
return Incompatible;
return Compatible;
}
@@ -5226,7 +5260,18 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (getLangOptions().CPlusPlus) {
if (LCanPointeeTy == RCanPointeeTy)
return ResultTy;
-
+ if (!isRelational &&
+ (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
+ // Valid unless comparison between non-null pointer and function pointer
+ // This is a gcc extension compatibility comparison.
+ if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+ && !LHSIsNull && !RHSIsNull) {
+ Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+ return ResultTy;
+ }
+ }
// C++ [expr.rel]p2:
// [...] Pointer conversions (4.10) and qualification
// conversions (4.4) are performed on pointer operands (or on
@@ -5503,7 +5548,7 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
return InvalidOperands(Loc, lex, rex);
if (PerformImplicitConversion(lex, Context.BoolTy, LHS,
- "passing", /*IgnoreBaseAccess=*/false))
+ AA_Passing, /*IgnoreBaseAccess=*/false))
return InvalidOperands(Loc, lex, rex);
StandardConversionSequence RHS;
@@ -5512,7 +5557,7 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
return InvalidOperands(Loc, lex, rex);
if (PerformImplicitConversion(rex, Context.BoolTy, RHS,
- "passing", /*IgnoreBaseAccess=*/false))
+ AA_Passing, /*IgnoreBaseAccess=*/false))
return InvalidOperands(Loc, lex, rex);
// C++ [expr.log.and]p2
@@ -5587,6 +5632,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_NoSetterProperty:
Diag = diag::error_nosetter_property_assignment;
break;
+ case Expr::MLV_SubObjCPropertySetting:
+ Diag = diag::error_no_subobject_property_setting;
+ break;
}
SourceRange Assign;
@@ -5651,7 +5699,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
}
if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
- RHS, "assigning"))
+ RHS, AA_Assigning))
return QualType();
// C99 6.5.16p3: The type of an assignment expression is the type of the
@@ -5734,7 +5782,7 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
<< ResType << Op->getSourceRange();
} else {
Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
- << ResType << Op->getSourceRange();
+ << ResType << int(isInc) << Op->getSourceRange();
return QualType();
}
// At this point, we know we have a real, complex or pointer type.
@@ -6478,28 +6526,12 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
// Get the decl corresponding to this.
RecordDecl *RD = RC->getDecl();
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- if (!CRD->isPOD() && !DidWarnAboutNonPOD) {
- switch (ExprEvalContexts.back().Context ) {
- case Unevaluated:
- // The argument will never be evaluated, so don't complain.
- break;
-
- case PotentiallyEvaluated:
- ExprError(Diag(BuiltinLoc, diag::warn_offsetof_non_pod_type)
- << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
- << Res->getType());
- DidWarnAboutNonPOD = true;
- break;
-
- case PotentiallyPotentiallyEvaluated:
- ExprEvalContexts.back().addDiagnostic(BuiltinLoc,
- PDiag(diag::warn_offsetof_non_pod_type)
- << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
- << Res->getType());
- DidWarnAboutNonPOD = true;
- break;
- }
- }
+ if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
+ DiagRuntimeBehavior(BuiltinLoc,
+ PDiag(diag::warn_offsetof_non_pod_type)
+ << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
+ << Res->getType()))
+ DidWarnAboutNonPOD = true;
}
LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
@@ -6847,7 +6879,7 @@ MakeObjCStringLiteralCodeModificationHint(Sema& SemaRef,
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
- Expr *SrcExpr, const char *Flavor) {
+ Expr *SrcExpr, AssignmentAction Action) {
// Decode the result (notice that AST's are still created for extensions).
bool isInvalid = false;
unsigned DiagKind;
@@ -6910,7 +6942,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
break;
}
- Diag(Loc, DiagKind) << DstType << SrcType << Flavor
+ Diag(Loc, DiagKind) << DstType << SrcType << Action
<< SrcExpr->getSourceRange() << Hint;
return isInvalid;
}
@@ -7053,7 +7085,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (!Constructor->isUsed())
DefineImplicitDefaultConstructor(Loc, Constructor);
} else if (Constructor->isImplicit() &&
- Constructor->isCopyConstructor(Context, TypeQuals)) {
+ Constructor->isCopyConstructor(TypeQuals)) {
if (!Constructor->isUsed())
DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
}
@@ -7120,6 +7152,41 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
}
}
+/// \brief Emit a diagnostic that describes an effect on the run-time behavior
+/// of the program being compiled.
+///
+/// This routine emits the given diagnostic when the code currently being
+/// type-checked is "potentially evaluated", meaning that there is a
+/// possibility that the code will actually be executable. Code in sizeof()
+/// expressions, code used only during overload resolution, etc., are not
+/// potentially evaluated. This routine will suppress such diagnostics or,
+/// in the absolutely nutty case of potentially potentially evaluated
+/// expressions (C++ typeid), queue the diagnostic to potentially emit it
+/// later.
+///
+/// This routine should be used for all diagnostics that describe the run-time
+/// behavior of a program, such as passing a non-POD value through an ellipsis.
+/// Failure to do so will likely result in spurious diagnostics or failures
+/// during overload resolution or within sizeof/alignof/typeof/typeid.
+bool Sema::DiagRuntimeBehavior(SourceLocation Loc,
+ const PartialDiagnostic &PD) {
+ switch (ExprEvalContexts.back().Context ) {
+ case Unevaluated:
+ // The argument will never be evaluated, so don't complain.
+ break;
+
+ case PotentiallyEvaluated:
+ Diag(Loc, PD);
+ return true;
+
+ case PotentiallyPotentiallyEvaluated:
+ ExprEvalContexts.back().addDiagnostic(Loc, PD);
+ break;
+ }
+
+ return false;
+}
+
bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
CallExpr *CE, FunctionDecl *FD) {
if (ReturnType->isVoidType() || !ReturnType->isIncompleteType())
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 6d991b6..5f723f9 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -31,9 +31,29 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
if (!StdNamespace)
return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
- if (isType)
+ if (isType) {
+ // C++ [expr.typeid]p4:
+ // The top-level cv-qualifiers of the lvalue expression or the type-id
+ // that is the operand of typeid are always ignored.
// FIXME: Preserve type source info.
- TyOrExpr = GetTypeFromParser(TyOrExpr).getAsOpaquePtr();
+ // FIXME: Preserve the type before we stripped the cv-qualifiers?
+ QualType T = GetTypeFromParser(TyOrExpr);
+ if (T.isNull())
+ return ExprError();
+
+ // C++ [expr.typeid]p4:
+ // If the type of the type-id is a class type or a reference to a class
+ // type, the class shall be completely-defined.
+ QualType CheckT = T;
+ if (const ReferenceType *RefType = CheckT->getAs<ReferenceType>())
+ CheckT = RefType->getPointeeType();
+
+ if (CheckT->getAs<RecordType>() &&
+ RequireCompleteType(OpLoc, CheckT, diag::err_incomplete_typeid))
+ return ExprError();
+
+ TyOrExpr = T.getUnqualifiedType().getAsOpaquePtr();
+ }
IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
@@ -45,21 +65,36 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl);
if (!isType) {
- // C++0x [expr.typeid]p3:
- // When typeid is applied to an expression other than an lvalue of a
- // polymorphic class type [...] [the] expression is an unevaluated
- // operand.
-
- // FIXME: if the type of the expression is a class type, the class
- // shall be completely defined.
bool isUnevaluatedOperand = true;
Expr *E = static_cast<Expr *>(TyOrExpr);
- if (E && !E->isTypeDependent() && E->isLvalue(Context) == Expr::LV_Valid) {
+ if (E && !E->isTypeDependent()) {
QualType T = E->getType();
if (const RecordType *RecordT = T->getAs<RecordType>()) {
CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
- if (RecordD->isPolymorphic())
+ // C++ [expr.typeid]p3:
+ // When typeid is applied to an expression other than an lvalue of a
+ // polymorphic class type [...] [the] expression is an unevaluated
+ // operand. [...]
+ if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid)
isUnevaluatedOperand = false;
+ else {
+ // C++ [expr.typeid]p3:
+ // [...] If the type of the expression is a class type, the class
+ // shall be completely-defined.
+ if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid))
+ return ExprError();
+ }
+ }
+
+ // C++ [expr.typeid]p4:
+ // [...] If the type of the type-id is a reference to a possibly
+ // cv-qualified type, the result of the typeid expression refers to a
+ // std::type_info object representing the cv-unqualified referenced
+ // type.
+ if (T.hasQualifiers()) {
+ ImpCastExprToType(E, T.getUnqualifiedType(), CastExpr::CK_NoOp,
+ E->isLvalue(Context));
+ TyOrExpr = E;
}
}
@@ -102,8 +137,15 @@ Sema::ActOnCXXThrow(SourceLocation OpLoc, ExprArg E) {
/// CheckCXXThrowOperand - Validate the operand of a throw.
bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
// C++ [except.throw]p3:
- // [...] adjusting the type from "array of T" or "function returning T"
- // to "pointer to T" or "pointer to function returning T", [...]
+ // A throw-expression initializes a temporary object, called the exception
+ // object, the type of which is determined by removing any top-level
+ // cv-qualifiers from the static type of the operand of throw and adjusting
+ // the type from "array of T" or "function returning T" to "pointer to T"
+ // or "pointer to function returning T", [...]
+ if (E->getType().hasQualifiers())
+ ImpCastExprToType(E, E->getType().getUnqualifiedType(), CastExpr::CK_NoOp,
+ E->isLvalue(Context) == Expr::LV_Valid);
+
DefaultFunctionArrayConversion(E);
// If the type of the exception would be an incomplete type or a pointer
@@ -425,74 +467,61 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
bool Init = ConstructorLParen.isValid();
// --- Choosing a constructor ---
- // C++ 5.3.4p15
- // 1) If T is a POD and there's no initializer (ConstructorLParen is invalid)
- // the object is not initialized. If the object, or any part of it, is
- // const-qualified, it's an error.
- // 2) If T is a POD and there's an empty initializer, the object is value-
- // initialized.
- // 3) If T is a POD and there's one initializer argument, the object is copy-
- // constructed.
- // 4) If T is a POD and there's more initializer arguments, it's an error.
- // 5) If T is not a POD, the initializer arguments are used as constructor
- // arguments.
- //
- // Or by the C++0x formulation:
- // 1) If there's no initializer, the object is default-initialized according
- // to C++0x rules.
- // 2) Otherwise, the object is direct-initialized.
CXXConstructorDecl *Constructor = 0;
Expr **ConsArgs = (Expr**)ConstructorArgs.get();
- const RecordType *RT;
unsigned NumConsArgs = ConstructorArgs.size();
ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this);
- if (AllocType->isDependentType() ||
- Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
- // Skip all the checks.
- } else if ((RT = AllocType->getAs<RecordType>()) &&
- !AllocType->isAggregateType()) {
- InitializationKind InitKind = InitializationKind::CreateDefault(TypeLoc);
- if (NumConsArgs > 0)
- InitKind = InitializationKind::CreateDirect(TypeLoc,
- PlacementLParen,
- PlacementRParen);
- Constructor = PerformInitializationByConstructor(
- AllocType, move(ConstructorArgs),
- TypeLoc,
- SourceRange(TypeLoc, ConstructorRParen),
- RT->getDecl()->getDeclName(),
- InitKind,
- ConvertedConstructorArgs);
- if (!Constructor)
+ if (!AllocType->isDependentType() &&
+ !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
+ // C++0x [expr.new]p15:
+ // A new-expression that creates an object of type T initializes that
+ // object as follows:
+ InitializationKind Kind
+ // - If the new-initializer is omitted, the object is default-
+ // initialized (8.5); if no initialization is performed,
+ // the object has indeterminate value
+ = !Init? InitializationKind::CreateDefault(TypeLoc)
+ // - Otherwise, the new-initializer is interpreted according to the
+ // initialization rules of 8.5 for direct-initialization.
+ : InitializationKind::CreateDirect(TypeLoc,
+ ConstructorLParen,
+ ConstructorRParen);
+
+ InitializedEntity Entity
+ = InitializedEntity::InitializeNew(StartLoc, AllocType);
+ InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs);
+ OwningExprResult FullInit = InitSeq.Perform(*this, Entity, Kind,
+ move(ConstructorArgs));
+ if (FullInit.isInvalid())
return ExprError();
-
- // Take the converted constructor arguments and use them for the new
- // expression.
- NumConsArgs = ConvertedConstructorArgs.size();
- ConsArgs = (Expr **)ConvertedConstructorArgs.take();
- } else {
- if (!Init) {
- // FIXME: Check that no subpart is const.
- if (AllocType.isConstQualified())
- return ExprError(Diag(StartLoc, diag::err_new_uninitialized_const)
- << TypeRange);
- } else if (NumConsArgs == 0) {
- // Object is value-initialized. Do nothing.
- } else if (NumConsArgs == 1) {
- // Object is direct-initialized.
- // FIXME: What DeclarationName do we pass in here?
- if (CheckInitializerTypes(ConsArgs[0], AllocType, StartLoc,
- DeclarationName() /*AllocType.getAsString()*/,
- /*DirectInit=*/true))
- return ExprError();
+
+ // FullInit is our initializer; walk through it to determine if it's a
+ // constructor call, which CXXNewExpr handles directly.
+ if (Expr *FullInitExpr = (Expr *)FullInit.get()) {
+ if (CXXBindTemporaryExpr *Binder
+ = dyn_cast<CXXBindTemporaryExpr>(FullInitExpr))
+ FullInitExpr = Binder->getSubExpr();
+ if (CXXConstructExpr *Construct
+ = dyn_cast<CXXConstructExpr>(FullInitExpr)) {
+ Constructor = Construct->getConstructor();
+ for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(),
+ AEnd = Construct->arg_end();
+ A != AEnd; ++A)
+ ConvertedConstructorArgs.push_back(A->Retain());
+ } else {
+ // Take the converted initializer.
+ ConvertedConstructorArgs.push_back(FullInit.release());
+ }
} else {
- return ExprError(Diag(StartLoc,
- diag::err_builtin_direct_init_more_than_one_arg)
- << SourceRange(ConstructorLParen, ConstructorRParen));
+ // No initialization required.
}
+
+ // Take the converted arguments and use them for the new expression.
+ NumConsArgs = ConvertedConstructorArgs.size();
+ ConsArgs = (Expr **)ConvertedConstructorArgs.take();
}
-
+
// FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16)
PlacementArgs.release();
@@ -631,10 +660,9 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
// Whatch out for variadic allocator function.
unsigned NumArgsInFnDecl = FnDecl->getNumParams();
for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
- // FIXME: Passing word to diagnostic.
if (PerformCopyInitialization(Args[i],
FnDecl->getParamDecl(i)->getType(),
- "passing"))
+ AA_Passing))
return true;
}
Operator = FnDecl;
@@ -720,13 +748,14 @@ void Sema::DeclareGlobalNewDelete() {
QualType VoidPtr = Context.getPointerType(Context.VoidTy);
QualType SizeT = Context.getSizeType();
+ bool AssumeSaneOperatorNew = getLangOptions().AssumeSaneOperatorNew;
DeclareGlobalAllocationFunction(
Context.DeclarationNames.getCXXOperatorName(OO_New),
- VoidPtr, SizeT);
+ VoidPtr, SizeT, AssumeSaneOperatorNew);
DeclareGlobalAllocationFunction(
Context.DeclarationNames.getCXXOperatorName(OO_Array_New),
- VoidPtr, SizeT);
+ VoidPtr, SizeT, AssumeSaneOperatorNew);
DeclareGlobalAllocationFunction(
Context.DeclarationNames.getCXXOperatorName(OO_Delete),
Context.VoidTy, VoidPtr);
@@ -738,7 +767,8 @@ void Sema::DeclareGlobalNewDelete() {
/// DeclareGlobalAllocationFunction - Declares a single implicit global
/// allocation function if it doesn't already exist.
void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
- QualType Return, QualType Argument) {
+ QualType Return, QualType Argument,
+ bool AddMallocAttr) {
DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
// Check if this function is already declared.
@@ -749,7 +779,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
// FIXME: Do we need to check for default arguments here?
FunctionDecl *Func = cast<FunctionDecl>(*Alloc);
if (Func->getNumParams() == 1 &&
- Context.getCanonicalType(Func->getParamDecl(0)->getType())==Argument)
+ Context.getCanonicalType(
+ Func->getParamDecl(0)->getType().getUnqualifiedType()) == Argument)
return;
}
}
@@ -771,6 +802,10 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name,
FnType, /*TInfo=*/0, FunctionDecl::None, false, true);
Alloc->setImplicit();
+
+ if (AddMallocAttr)
+ Alloc->addAttr(::new (Context) MallocAttr());
+
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
0, Argument, /*TInfo=*/0,
VarDecl::None, 0);
@@ -876,7 +911,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
Operand.release();
if (!PerformImplicitConversion(Ex,
ObjectPtrConversions.front()->getConversionType(),
- "converting")) {
+ AA_Converting)) {
Operand = Owned(Ex);
Type = Ex->getType();
}
@@ -1027,16 +1062,16 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
/// resolution works differently in that case.
bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
- const char *Flavor, bool AllowExplicit,
+ AssignmentAction Action, bool AllowExplicit,
bool Elidable) {
ImplicitConversionSequence ICS;
- return PerformImplicitConversion(From, ToType, Flavor, AllowExplicit,
+ return PerformImplicitConversion(From, ToType, Action, AllowExplicit,
Elidable, ICS);
}
bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
- const char *Flavor, bool AllowExplicit,
+ AssignmentAction Action, bool AllowExplicit,
bool Elidable,
ImplicitConversionSequence& ICS) {
ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
@@ -1054,7 +1089,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
/*ForceRValue=*/false,
/*InOverloadResolution=*/false);
}
- return PerformImplicitConversion(From, ToType, ICS, Flavor);
+ return PerformImplicitConversion(From, ToType, ICS, Action);
}
/// BuildCXXDerivedToBaseExpr - This routine generates the suitable AST
@@ -1062,8 +1097,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
/// necessary information is passed in ICS.
bool
Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
- const ImplicitConversionSequence& ICS,
- const char *Flavor) {
+ const ImplicitConversionSequence& ICS) {
QualType BaseType =
QualType::getFromOpaquePtr(ICS.UserDefined.After.ToTypePtr);
// Must do additional defined to base conversion.
@@ -1095,15 +1129,15 @@ Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
/// expression From to the type ToType using the pre-computed implicit
/// conversion sequence ICS. Returns true if there was an error, false
/// otherwise. The expression From is replaced with the converted
-/// expression. Flavor is the kind of conversion we're performing,
+/// expression. Action is the kind of conversion we're performing,
/// used in the error message.
bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
const ImplicitConversionSequence &ICS,
- const char* Flavor, bool IgnoreBaseAccess) {
+ AssignmentAction Action, bool IgnoreBaseAccess) {
switch (ICS.ConversionKind) {
case ImplicitConversionSequence::StandardConversion:
- if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor,
+ if (PerformImplicitConversion(From, ToType, ICS.Standard, Action,
IgnoreBaseAccess))
return true;
break;
@@ -1136,7 +1170,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// Whatch out for elipsis conversion.
if (!ICS.UserDefined.EllipsisConversion) {
if (PerformImplicitConversion(From, BeforeToType,
- ICS.UserDefined.Before, "converting",
+ ICS.UserDefined.Before, AA_Converting,
IgnoreBaseAccess))
return true;
}
@@ -1156,7 +1190,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// there's some nasty stuff involving MaybeBindToTemporary going on here.
if (ICS.UserDefined.After.Second == ICK_Derived_To_Base &&
ICS.UserDefined.After.CopyConstructor) {
- return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor);
+ return BuildCXXDerivedToBaseExpr(From, CastKind, ICS);
}
if (ICS.UserDefined.After.CopyConstructor) {
@@ -1167,7 +1201,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
}
return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
- "converting", IgnoreBaseAccess);
+ AA_Converting, IgnoreBaseAccess);
}
case ImplicitConversionSequence::EllipsisConversion:
@@ -1191,7 +1225,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
const StandardConversionSequence& SCS,
- const char *Flavor, bool IgnoreBaseAccess) {
+ AssignmentAction Action, bool IgnoreBaseAccess) {
// Overall FIXME: we are recomputing too many types here and doing far too
// much extra work. What this means is that we need to keep track of more
// information that is computed when we try the implicit conversion initially,
@@ -1323,7 +1357,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// Diagnose incompatible Objective-C conversions
Diag(From->getSourceRange().getBegin(),
diag::ext_typecheck_convert_incompatible_pointer)
- << From->getType() << ToType << Flavor
+ << From->getType() << ToType << Action
<< From->getSourceRange();
}
@@ -1595,9 +1629,9 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
case OR_Success:
// We found a match. Perform the conversions on the arguments and move on.
if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
- Best->Conversions[0], "converting") ||
+ Best->Conversions[0], Sema::AA_Converting) ||
Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1],
- Best->Conversions[1], "converting"))
+ Best->Conversions[1], Sema::AA_Converting))
break;
return false;
@@ -1655,7 +1689,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E,
/*AllowExplicit=*/false,
/*ForceRValue=*/false);
}
- if (Self.PerformImplicitConversion(E, TargetType(ICS), ICS, "converting"))
+ if (Self.PerformImplicitConversion(E, TargetType(ICS), ICS, Sema::AA_Converting))
return true;
return false;
}
@@ -1879,9 +1913,9 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
LPointee = Context.getQualifiedType(LPointee, MergedQuals);
QualType Common
= Context.getMemberPointerType(LPointee, MoreDerived.getTypePtr());
- if (PerformImplicitConversion(LHS, Common, "converting"))
+ if (PerformImplicitConversion(LHS, Common, Sema::AA_Converting))
return QualType();
- if (PerformImplicitConversion(RHS, Common, "converting"))
+ if (PerformImplicitConversion(RHS, Common, Sema::AA_Converting))
return QualType();
return Common;
}
@@ -2046,13 +2080,13 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
&& E2ToC2.ConversionKind !=
ImplicitConversionSequence::BadConversion;
if (ToC1Viable && !ToC2Viable) {
- if (!PerformImplicitConversion(E1, Composite1, E1ToC1, "converting") &&
- !PerformImplicitConversion(E2, Composite1, E2ToC1, "converting"))
+ if (!PerformImplicitConversion(E1, Composite1, E1ToC1, Sema::AA_Converting) &&
+ !PerformImplicitConversion(E2, Composite1, E2ToC1, Sema::AA_Converting))
return Composite1;
}
if (ToC2Viable && !ToC1Viable) {
- if (!PerformImplicitConversion(E1, Composite2, E1ToC2, "converting") &&
- !PerformImplicitConversion(E2, Composite2, E2ToC2, "converting"))
+ if (!PerformImplicitConversion(E1, Composite2, E1ToC2, Sema::AA_Converting) &&
+ !PerformImplicitConversion(E2, Composite2, E2ToC2, Sema::AA_Converting))
return Composite2;
}
return QualType();
@@ -2062,6 +2096,8 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (!Context.getLangOptions().CPlusPlus)
return Owned(E);
+ assert(!isa<CXXBindTemporaryExpr>(E) && "Double-bound temporary?");
+
const RecordType *RT = E->getType()->getAs<RecordType>();
if (!RT)
return Owned(E);
@@ -2089,8 +2125,7 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E));
}
-Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
- bool ShouldDestroyTemps) {
+Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr) {
assert(SubExpr && "sub expression can't be null!");
unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
@@ -2100,8 +2135,31 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
Expr *E = CXXExprWithTemporaries::Create(Context, SubExpr,
&ExprTemporaries[FirstTemporary],
- ExprTemporaries.size() - FirstTemporary,
- ShouldDestroyTemps);
+ ExprTemporaries.size() - FirstTemporary);
+ ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary,
+ ExprTemporaries.end());
+
+ return E;
+}
+
+Sema::OwningExprResult
+Sema::MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr) {
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ return Owned(MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>()));
+}
+
+FullExpr Sema::CreateFullExpr(Expr *SubExpr) {
+ unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
+ assert(ExprTemporaries.size() >= FirstTemporary);
+
+ unsigned NumTemporaries = ExprTemporaries.size() - FirstTemporary;
+ CXXTemporary **Temporaries =
+ NumTemporaries == 0 ? 0 : &ExprTemporaries[FirstTemporary];
+
+ FullExpr E = FullExpr::Create(Context, SubExpr, Temporaries, NumTemporaries);
+
ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary,
ExprTemporaries.end());
@@ -2243,9 +2301,7 @@ Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,
Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
Expr *FullExpr = Arg.takeAs<Expr>();
if (FullExpr)
- FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr,
- /*ShouldDestroyTemps=*/true);
-
+ FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr);
return Owned(FullExpr);
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index b78c10b..2e31e47 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -205,7 +205,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
IsError |=
DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
- argExpr, "sending");
+ argExpr, AA_Sending);
}
// Promote additional arguments to variadic methods.
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 4518465..3ef5156 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -16,11 +16,13 @@
//===----------------------------------------------------------------------===//
#include "SemaInit.h"
+#include "Lookup.h"
#include "Sema.h"
#include "clang/Parse/Designator.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
#include "llvm/Support/ErrorHandling.h"
#include <map>
using namespace clang;
@@ -73,7 +75,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
if (S.getLangOptions().CPlusPlus) {
// FIXME: I dislike this error message. A lot.
if (S.PerformImplicitConversion(Init, DeclType,
- "initializing", DirectInit)) {
+ Sema::AA_Initializing, DirectInit)) {
ImplicitConversionSequence ICS;
OverloadCandidateSet CandidateSet;
if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined,
@@ -81,7 +83,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
true, false, false) != OR_Ambiguous)
return S.Diag(Init->getSourceRange().getBegin(),
diag::err_typecheck_convert_incompatible)
- << DeclType << Init->getType() << "initializing"
+ << DeclType << Init->getType() << Sema::AA_Initializing
<< Init->getSourceRange();
S.Diag(Init->getSourceRange().getBegin(),
diag::err_typecheck_convert_ambiguous)
@@ -95,7 +97,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
Sema::AssignConvertType ConvTy =
S.CheckSingleAssignmentConstraints(DeclType, Init);
return S.DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
- InitType, Init, "initializing");
+ InitType, Init, Sema::AA_Initializing);
}
static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
@@ -134,172 +136,6 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
Str->setType(DeclT);
}
-bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
- SourceLocation InitLoc,
- DeclarationName InitEntity, bool DirectInit) {
- if (DeclType->isDependentType() ||
- Init->isTypeDependent() || Init->isValueDependent()) {
- // We have either a dependent type or a type- or value-dependent
- // initializer, so we don't perform any additional checking at
- // this point.
-
- // If the declaration is a non-dependent, incomplete array type
- // that has an initializer, then its type will be completed once
- // the initializer is instantiated.
- if (!DeclType->isDependentType()) {
- if (const IncompleteArrayType *ArrayT
- = Context.getAsIncompleteArrayType(DeclType)) {
- if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
- if (!ILE->isTypeDependent()) {
- // Compute the constant array type from the length of the
- // initializer list.
- // FIXME: This will be wrong if there are designated
- // initializations. Good thing they don't exist in C++!
- llvm::APInt NumElements(Context.getTypeSize(Context.getSizeType()),
- ILE->getNumInits());
- llvm::APInt Zero(Context.getTypeSize(Context.getSizeType()), 0);
- if (NumElements == Zero) {
- // Sizing an array implicitly to zero is not allowed by ISO C,
- // but is supported by GNU.
- Diag(ILE->getLocStart(), diag::ext_typecheck_zero_array_size);
- }
-
- DeclType = Context.getConstantArrayType(ArrayT->getElementType(),
- NumElements,
- ArrayT->getSizeModifier(),
- ArrayT->getIndexTypeCVRQualifiers());
- return false;
- }
- }
-
- // Make the array type-dependent by making it dependently-sized.
- DeclType = Context.getDependentSizedArrayType(ArrayT->getElementType(),
- /*NumElts=*/0,
- ArrayT->getSizeModifier(),
- ArrayT->getIndexTypeCVRQualifiers(),
- SourceRange());
- }
- }
-
- return false;
- }
-
- // C++ [dcl.init.ref]p1:
- // A variable declared to be a T& or T&&, that is "reference to type T"
- // (8.3.2), shall be initialized by an object, or function, of
- // type T or by an object that can be converted into a T.
- if (DeclType->isReferenceType())
- return CheckReferenceInit(Init, DeclType, InitLoc,
- /*SuppressUserConversions=*/false,
- /*AllowExplicit=*/DirectInit,
- /*ForceRValue=*/false);
-
- // C99 6.7.8p3: The type of the entity to be initialized shall be an array
- // of unknown size ("[]") or an object type that is not a variable array type.
- if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType))
- return Diag(InitLoc, diag::err_variable_object_no_init)
- << VAT->getSizeExpr()->getSourceRange();
-
- InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
- if (!InitList) {
- // FIXME: Handle wide strings
- if (Expr *Str = IsStringInit(Init, DeclType, Context)) {
- CheckStringInit(Str, DeclType, *this);
- return false;
- }
-
- // C++ [dcl.init]p14:
- // -- If the destination type is a (possibly cv-qualified) class
- // type:
- if (getLangOptions().CPlusPlus && DeclType->isRecordType()) {
- QualType DeclTypeC = Context.getCanonicalType(DeclType);
- QualType InitTypeC = Context.getCanonicalType(Init->getType());
-
- // -- If the initialization is direct-initialization, or if it is
- // copy-initialization where the cv-unqualified version of the
- // source type is the same class as, or a derived class of, the
- // class of the destination, constructors are considered.
- if ((DeclTypeC.getLocalUnqualifiedType()
- == InitTypeC.getLocalUnqualifiedType()) ||
- IsDerivedFrom(InitTypeC, DeclTypeC)) {
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(DeclType->getAs<RecordType>()->getDecl());
-
- // No need to make a CXXConstructExpr if both the ctor and dtor are
- // trivial.
- if (RD->hasTrivialConstructor() && RD->hasTrivialDestructor())
- return false;
-
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
-
- // FIXME: Poor location information
- InitializationKind InitKind
- = InitializationKind::CreateCopy(Init->getLocStart(),
- SourceLocation());
- if (DirectInit)
- InitKind = InitializationKind::CreateDirect(Init->getLocStart(),
- SourceLocation(),
- SourceLocation());
- CXXConstructorDecl *Constructor
- = PerformInitializationByConstructor(DeclType,
- MultiExprArg(*this,
- (void **)&Init, 1),
- InitLoc, Init->getSourceRange(),
- InitEntity, InitKind,
- ConstructorArgs);
- if (!Constructor)
- return true;
-
- OwningExprResult InitResult =
- BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
- DeclType, Constructor,
- move_arg(ConstructorArgs));
- if (InitResult.isInvalid())
- return true;
-
- Init = InitResult.takeAs<Expr>();
- return false;
- }
-
- // -- Otherwise (i.e., for the remaining copy-initialization
- // cases), user-defined conversion sequences that can
- // convert from the source type to the destination type or
- // (when a conversion function is used) to a derived class
- // thereof are enumerated as described in 13.3.1.4, and the
- // best one is chosen through overload resolution
- // (13.3). If the conversion cannot be done or is
- // ambiguous, the initialization is ill-formed. The
- // function selected is called with the initializer
- // expression as its argument; if the function is a
- // constructor, the call initializes a temporary of the
- // destination type.
- // FIXME: We're pretending to do copy elision here; return to this when we
- // have ASTs for such things.
- if (!PerformImplicitConversion(Init, DeclType, "initializing"))
- return false;
-
- if (InitEntity)
- return Diag(InitLoc, diag::err_cannot_initialize_decl)
- << InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
- << Init->getType() << Init->getSourceRange();
- return Diag(InitLoc, diag::err_cannot_initialize_decl_noname)
- << DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
- << Init->getType() << Init->getSourceRange();
- }
-
- // C99 6.7.8p16.
- if (DeclType->isArrayType())
- return Diag(Init->getLocStart(), diag::err_array_init_list_required)
- << Init->getSourceRange();
-
- return CheckSingleInitializer(Init, DeclType, DirectInit, *this);
- }
-
- bool hadError = CheckInitList(InitList, DeclType);
- Init = InitList;
- return hadError;
-}
-
//===----------------------------------------------------------------------===//
// Semantic checking for initializer lists.
//===----------------------------------------------------------------------===//
@@ -399,9 +235,14 @@ class InitListChecker {
int numArrayElements(QualType DeclType);
int numStructUnionElements(QualType DeclType);
- void FillInValueInitializations(InitListExpr *ILE);
+ void FillInValueInitForField(unsigned Init, FieldDecl *Field,
+ const InitializedEntity &ParentEntity,
+ InitListExpr *ILE, bool &RequiresSecondPass);
+ void FillInValueInitializations(const InitializedEntity &Entity,
+ InitListExpr *ILE, bool &RequiresSecondPass);
public:
- InitListChecker(Sema &S, InitListExpr *IL, QualType &T);
+ InitListChecker(Sema &S, const InitializedEntity &Entity,
+ InitListExpr *IL, QualType &T);
bool HadError() { return hadError; }
// @brief Retrieves the fully-structured initializer list used for
@@ -410,10 +251,75 @@ public:
};
} // end anonymous namespace
+void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
+ const InitializedEntity &ParentEntity,
+ InitListExpr *ILE,
+ bool &RequiresSecondPass) {
+ SourceLocation Loc = ILE->getSourceRange().getBegin();
+ unsigned NumInits = ILE->getNumInits();
+ InitializedEntity MemberEntity
+ = InitializedEntity::InitializeMember(Field, &ParentEntity);
+ if (Init >= NumInits || !ILE->getInit(Init)) {
+ // FIXME: We probably don't need to handle references
+ // specially here, since value-initialization of references is
+ // handled in InitializationSequence.
+ if (Field->getType()->isReferenceType()) {
+ // C++ [dcl.init.aggr]p9:
+ // If an incomplete or empty initializer-list leaves a
+ // member of reference type uninitialized, the program is
+ // ill-formed.
+ SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
+ << Field->getType()
+ << ILE->getSyntacticForm()->getSourceRange();
+ SemaRef.Diag(Field->getLocation(),
+ diag::note_uninit_reference_member);
+ hadError = true;
+ return;
+ }
+
+ InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+ true);
+ InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
+ if (!InitSeq) {
+ InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
+ hadError = true;
+ return;
+ }
+
+ Sema::OwningExprResult MemberInit
+ = InitSeq.Perform(SemaRef, MemberEntity, Kind,
+ Sema::MultiExprArg(SemaRef, 0, 0));
+ if (MemberInit.isInvalid()) {
+ hadError = true;
+ return;
+ }
+
+ if (hadError) {
+ // Do nothing
+ } else if (Init < NumInits) {
+ ILE->setInit(Init, MemberInit.takeAs<Expr>());
+ } else if (InitSeq.getKind()
+ == InitializationSequence::ConstructorInitialization) {
+ // Value-initialization requires a constructor call, so
+ // extend the initializer list to include the constructor
+ // call and make a note that we'll need to take another pass
+ // through the initializer list.
+ ILE->updateInit(Init, MemberInit.takeAs<Expr>());
+ RequiresSecondPass = true;
+ }
+ } else if (InitListExpr *InnerILE
+ = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+ FillInValueInitializations(MemberEntity, InnerILE,
+ RequiresSecondPass);
+}
+
/// Recursively replaces NULL values within the given initializer list
/// with expressions that perform value-initialization of the
/// appropriate type.
-void InitListChecker::FillInValueInitializations(InitListExpr *ILE) {
+void
+InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
+ InitListExpr *ILE,
+ bool &RequiresSecondPass) {
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
"Should not have void type");
SourceLocation Loc = ILE->getSourceRange().getBegin();
@@ -421,46 +327,32 @@ void InitListChecker::FillInValueInitializations(InitListExpr *ILE) {
Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
- unsigned Init = 0, NumInits = ILE->getNumInits();
- for (RecordDecl::field_iterator
- Field = RType->getDecl()->field_begin(),
- FieldEnd = RType->getDecl()->field_end();
- Field != FieldEnd; ++Field) {
- if (Field->isUnnamedBitfield())
- continue;
-
- if (Init >= NumInits || !ILE->getInit(Init)) {
- if (Field->getType()->isReferenceType()) {
- // C++ [dcl.init.aggr]p9:
- // If an incomplete or empty initializer-list leaves a
- // member of reference type uninitialized, the program is
- // ill-formed.
- SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
- << Field->getType()
- << ILE->getSyntacticForm()->getSourceRange();
- SemaRef.Diag(Field->getLocation(),
- diag::note_uninit_reference_member);
- hadError = true;
+ if (RType->getDecl()->isUnion() &&
+ ILE->getInitializedFieldInUnion())
+ FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
+ Entity, ILE, RequiresSecondPass);
+ else {
+ unsigned Init = 0;
+ for (RecordDecl::field_iterator
+ Field = RType->getDecl()->field_begin(),
+ FieldEnd = RType->getDecl()->field_end();
+ Field != FieldEnd; ++Field) {
+ if (Field->isUnnamedBitfield())
+ continue;
+
+ if (hadError)
return;
- } else if (SemaRef.CheckValueInitialization(Field->getType(), Loc)) {
- hadError = true;
+
+ FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
+ if (hadError)
return;
- }
- // FIXME: If value-initialization involves calling a constructor, should
- // we make that call explicit in the representation (even when it means
- // extending the initializer list)?
- if (Init < NumInits && !hadError)
- ILE->setInit(Init,
- new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()));
- } else if (InitListExpr *InnerILE
- = dyn_cast<InitListExpr>(ILE->getInit(Init)))
- FillInValueInitializations(InnerILE);
- ++Init;
+ ++Init;
- // Only look at the first initialization of a union.
- if (RType->getDecl()->isUnion())
- break;
+ // Only look at the first initialization of a union.
+ if (RType->getDecl()->isUnion())
+ break;
+ }
}
return;
@@ -468,39 +360,71 @@ void InitListChecker::FillInValueInitializations(InitListExpr *ILE) {
QualType ElementType;
+ InitializedEntity ElementEntity = Entity;
unsigned NumInits = ILE->getNumInits();
unsigned NumElements = NumInits;
if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
ElementType = AType->getElementType();
if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
NumElements = CAType->getSize().getZExtValue();
+ ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
+ 0, Entity);
} else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
ElementType = VType->getElementType();
NumElements = VType->getNumElements();
+ ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
+ 0, Entity);
} else
ElementType = ILE->getType();
+
for (unsigned Init = 0; Init != NumElements; ++Init) {
+ if (hadError)
+ return;
+
+ if (ElementEntity.getKind() == InitializedEntity::EK_ArrayOrVectorElement)
+ ElementEntity.setElementIndex(Init);
+
if (Init >= NumInits || !ILE->getInit(Init)) {
- if (SemaRef.CheckValueInitialization(ElementType, Loc)) {
+ InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+ true);
+ InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0);
+ if (!InitSeq) {
+ InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0);
hadError = true;
return;
}
- // FIXME: If value-initialization involves calling a constructor, should
- // we make that call explicit in the representation (even when it means
- // extending the initializer list)?
- if (Init < NumInits && !hadError)
- ILE->setInit(Init,
- new (SemaRef.Context) ImplicitValueInitExpr(ElementType));
+ Sema::OwningExprResult ElementInit
+ = InitSeq.Perform(SemaRef, ElementEntity, Kind,
+ Sema::MultiExprArg(SemaRef, 0, 0));
+ if (ElementInit.isInvalid()) {
+ hadError = true;
+ return;
+ }
+
+ if (hadError) {
+ // Do nothing
+ } else if (Init < NumInits) {
+ ILE->setInit(Init, ElementInit.takeAs<Expr>());
+ } else if (InitSeq.getKind()
+ == InitializationSequence::ConstructorInitialization) {
+ // Value-initialization requires a constructor call, so
+ // extend the initializer list to include the constructor
+ // call and make a note that we'll need to take another pass
+ // through the initializer list.
+ ILE->updateInit(Init, ElementInit.takeAs<Expr>());
+ RequiresSecondPass = true;
+ }
} else if (InitListExpr *InnerILE
- = dyn_cast<InitListExpr>(ILE->getInit(Init)))
- FillInValueInitializations(InnerILE);
+ = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+ FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass);
}
}
-InitListChecker::InitListChecker(Sema &S, InitListExpr *IL, QualType &T)
+InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
+ InitListExpr *IL, QualType &T)
: SemaRef(S) {
hadError = false;
@@ -511,8 +435,13 @@ InitListChecker::InitListChecker(Sema &S, InitListExpr *IL, QualType &T)
CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex,
/*TopLevelObject=*/true);
- if (!hadError)
- FillInValueInitializations(FullyStructuredList);
+ if (!hadError) {
+ bool RequiresSecondPass = false;
+ FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
+ if (RequiresSecondPass && !hadError)
+ FillInValueInitializations(Entity, FullyStructuredList,
+ RequiresSecondPass);
+ }
}
int InitListChecker::numArrayElements(QualType DeclType) {
@@ -743,7 +672,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion) {
if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS,
- "initializing"))
+ Sema::AA_Initializing))
hadError = true;
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
@@ -783,7 +712,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
} else {
// We cannot initialize this element, so let
// PerformCopyInitialization produce the appropriate diagnostic.
- SemaRef.PerformCopyInitialization(expr, ElemType, "initializing");
+ SemaRef.PerformCopyInitialization(expr, ElemType, Sema::AA_Initializing);
hadError = true;
++Index;
++StructuredIndex;
@@ -1358,22 +1287,33 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
// may find nothing, or may find a member of an anonymous
// struct/union.
DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
+ FieldDecl *ReplacementField = 0;
if (Lookup.first == Lookup.second) {
- // Name lookup didn't find anything.
- SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
- << FieldName << CurrentObjectType;
- ++Index;
- return true;
- } else if (!KnownField && isa<FieldDecl>(*Lookup.first) &&
- cast<RecordDecl>((*Lookup.first)->getDeclContext())
- ->isAnonymousStructOrUnion()) {
- // Handle an field designator that refers to a member of an
- // anonymous struct or union.
- ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx,
- cast<FieldDecl>(*Lookup.first),
- Field, FieldIndex);
- D = DIE->getDesignator(DesigIdx);
- } else {
+ // Name lookup didn't find anything. Determine whether this
+ // was a typo for another field name.
+ LookupResult R(SemaRef, FieldName, D->getFieldLoc(),
+ Sema::LookupMemberName);
+ if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl()) &&
+ (ReplacementField = R.getAsSingle<FieldDecl>()) &&
+ ReplacementField->getDeclContext()->getLookupContext()
+ ->Equals(RT->getDecl())) {
+ SemaRef.Diag(D->getFieldLoc(),
+ diag::err_field_designator_unknown_suggest)
+ << FieldName << CurrentObjectType << R.getLookupName()
+ << CodeModificationHint::CreateReplacement(D->getFieldLoc(),
+ R.getLookupName().getAsString());
+ } else {
+ SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
+ << FieldName << CurrentObjectType;
+ ++Index;
+ return true;
+ }
+ } else if (!KnownField) {
+ // Determine whether we found a field at all.
+ ReplacementField = dyn_cast<FieldDecl>(*Lookup.first);
+ }
+
+ if (!ReplacementField) {
// Name lookup found something, but it wasn't a field.
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
<< FieldName;
@@ -1382,6 +1322,32 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
++Index;
return true;
}
+
+ if (!KnownField &&
+ cast<RecordDecl>((ReplacementField)->getDeclContext())
+ ->isAnonymousStructOrUnion()) {
+ // Handle an field designator that refers to a member of an
+ // anonymous struct or union.
+ ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx,
+ ReplacementField,
+ Field, FieldIndex);
+ D = DIE->getDesignator(DesigIdx);
+ } else if (!KnownField) {
+ // The replacement field comes from typo correction; find it
+ // in the list of fields.
+ FieldIndex = 0;
+ Field = RT->getDecl()->field_begin();
+ for (; Field != FieldEnd; ++Field) {
+ if (Field->isUnnamedBitfield())
+ continue;
+
+ if (ReplacementField == *Field ||
+ Field->getIdentifier() == ReplacementField->getIdentifier())
+ break;
+
+ ++FieldIndex;
+ }
+ }
} else if (!KnownField &&
cast<RecordDecl>((*Field)->getDeclContext())
->isAnonymousStructOrUnion()) {
@@ -1844,101 +1810,27 @@ Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
return Owned(DIE);
}
-bool Sema::CheckInitList(InitListExpr *&InitList, QualType &DeclType) {
- InitListChecker CheckInitList(*this, InitList, DeclType);
+bool Sema::CheckInitList(const InitializedEntity &Entity,
+ InitListExpr *&InitList, QualType &DeclType) {
+ InitListChecker CheckInitList(*this, Entity, InitList, DeclType);
if (!CheckInitList.HadError())
InitList = CheckInitList.getFullyStructuredList();
return CheckInitList.HadError();
}
-/// \brief Diagnose any semantic errors with value-initialization of
-/// the given type.
-///
-/// Value-initialization effectively zero-initializes any types
-/// without user-declared constructors, and calls the default
-/// constructor for a for any type that has a user-declared
-/// constructor (C++ [dcl.init]p5). Value-initialization can fail when
-/// a type with a user-declared constructor does not have an
-/// accessible, non-deleted default constructor. In C, everything can
-/// be value-initialized, which corresponds to C's notion of
-/// initializing objects with static storage duration when no
-/// initializer is provided for that object.
-///
-/// \returns true if there was an error, false otherwise.
-bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) {
- // C++ [dcl.init]p5:
- //
- // To value-initialize an object of type T means:
-
- // -- if T is an array type, then each element is value-initialized;
- if (const ArrayType *AT = Context.getAsArrayType(Type))
- return CheckValueInitialization(AT->getElementType(), Loc);
-
- if (const RecordType *RT = Type->getAs<RecordType>()) {
- if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- // -- 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 initialization is ill-formed if T has no
- // accessible default constructor);
- if (ClassDecl->hasUserDeclaredConstructor()) {
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
-
- // FIXME: Poor location information
- CXXConstructorDecl *Constructor
- = PerformInitializationByConstructor(Type,
- MultiExprArg(*this, 0, 0),
- Loc, SourceRange(Loc),
- DeclarationName(),
- InitializationKind::CreateValue(Loc, Loc, Loc),
- ConstructorArgs);
- if (!Constructor)
- return true;
-
- OwningExprResult Init
- = BuildCXXConstructExpr(Loc, Type, Constructor,
- move_arg(ConstructorArgs));
- if (Init.isInvalid())
- return true;
-
- // FIXME: Actually perform the value-initialization!
- return false;
- }
- }
- }
-
- if (Type->isReferenceType()) {
- // C++ [dcl.init]p5:
- // [...] A program that calls for default-initialization or
- // value-initialization of an entity of reference type is
- // ill-formed. [...]
- // FIXME: Once we have code that goes through this path, add an actual
- // diagnostic :)
- }
-
- return false;
-}
-
//===----------------------------------------------------------------------===//
// Initialization entity
//===----------------------------------------------------------------------===//
-void InitializedEntity::InitDeclLoc() {
- assert((Kind == EK_Variable || Kind == EK_Parameter || Kind == EK_Member) &&
- "InitDeclLoc cannot be used with non-declaration entities.");
-
- if (TypeSourceInfo *DI = VariableOrMember->getTypeSourceInfo()) {
- TL = DI->getTypeLoc();
- return;
- }
-
- // FIXME: Once we've gone through the effort to create the fake
- // TypeSourceInfo, should we cache it in the declaration?
- // (If not, we "leak" it).
- TypeSourceInfo *DI = VariableOrMember->getASTContext()
- .CreateTypeSourceInfo(VariableOrMember->getType());
- DI->getTypeLoc().initialize(VariableOrMember->getLocation());
- TL = DI->getTypeLoc();
+InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
+ const InitializedEntity &Parent)
+ : Kind(EK_ArrayOrVectorElement), Parent(&Parent), Index(Index)
+{
+ if (const ArrayType *AT = Context.getAsArrayType(Parent.getType()))
+ Type = AT->getElementType();
+ else
+ Type = Parent.getType()->getAs<VectorType>()->getElementType();
}
InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
@@ -1947,13 +1839,54 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
InitializedEntity Result;
Result.Kind = EK_Base;
Result.Base = Base;
- // FIXME: CXXBaseSpecifier should store a TypeLoc.
- TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Base->getType());
- DI->getTypeLoc().initialize(Base->getSourceRange().getBegin());
- Result.TL = DI->getTypeLoc();
+ Result.Type = Base->getType();
return Result;
}
+DeclarationName InitializedEntity::getName() const {
+ switch (getKind()) {
+ case EK_Parameter:
+ if (!VariableOrMember)
+ return DeclarationName();
+ // Fall through
+
+ case EK_Variable:
+ case EK_Member:
+ return VariableOrMember->getDeclName();
+
+ case EK_Result:
+ case EK_Exception:
+ case EK_New:
+ case EK_Temporary:
+ case EK_Base:
+ case EK_ArrayOrVectorElement:
+ return DeclarationName();
+ }
+
+ // Silence GCC warning
+ return DeclarationName();
+}
+
+DeclaratorDecl *InitializedEntity::getDecl() const {
+ switch (getKind()) {
+ case EK_Variable:
+ case EK_Parameter:
+ case EK_Member:
+ return VariableOrMember;
+
+ case EK_Result:
+ case EK_Exception:
+ case EK_New:
+ case EK_Temporary:
+ case EK_Base:
+ case EK_ArrayOrVectorElement:
+ return 0;
+ }
+
+ // Silence GCC warning
+ return 0;
+}
+
//===----------------------------------------------------------------------===//
// Initialization sequence
//===----------------------------------------------------------------------===//
@@ -1971,6 +1904,8 @@ void InitializationSequence::Step::Destroy() {
case SK_ListInitialization:
case SK_ConstructorInitialization:
case SK_ZeroInitialization:
+ case SK_CAssignment:
+ case SK_StringInit:
break;
case SK_ConversionSequence:
@@ -2056,6 +1991,20 @@ void InitializationSequence::AddZeroInitializationStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddCAssignmentStep(QualType T) {
+ Step S;
+ S.Kind = SK_CAssignment;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddStringInitStep(QualType T) {
+ Step S;
+ S.Kind = SK_StringInit;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
OverloadingResult Result) {
SequenceKind = FailedSequence;
@@ -2081,7 +2030,7 @@ static void TryListInitialization(Sema &S,
// force us to perform more checking here.
Sequence.setSequenceKind(InitializationSequence::ListInitialization);
- QualType DestType = Entity.getType().getType();
+ QualType DestType = Entity.getType();
// C++ [dcl.init]p13:
// If T is a scalar type, then a declaration of the form
@@ -2125,7 +2074,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
Expr *Initializer,
bool AllowRValues,
InitializationSequence &Sequence) {
- QualType DestType = Entity.getType().getType();
+ QualType DestType = Entity.getType();
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
QualType T1 = cv1T1.getUnqualifiedType();
QualType cv2T2 = Initializer->getType();
@@ -2273,7 +2222,7 @@ static void TryReferenceInitialization(Sema &S,
InitializationSequence &Sequence) {
Sequence.setSequenceKind(InitializationSequence::ReferenceBinding);
- QualType DestType = Entity.getType().getType();
+ QualType DestType = Entity.getType();
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
QualType T1 = cv1T1.getUnqualifiedType();
QualType cv2T2 = Initializer->getType();
@@ -2437,7 +2386,12 @@ static void TryReferenceInitialization(Sema &S,
// this into an overloading ambiguity diagnostic. However, we need
// to keep that set as an OverloadCandidateSet rather than as some
// other kind of set.
- Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
+ if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+ else
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
return;
}
@@ -2463,7 +2417,8 @@ static void TryStringLiteralInitialization(Sema &S,
const InitializationKind &Kind,
Expr *Initializer,
InitializationSequence &Sequence) {
- // FIXME: Implement!
+ Sequence.setSequenceKind(InitializationSequence::StringInit);
+ Sequence.AddStringInitStep(Entity.getType());
}
/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
@@ -2475,7 +2430,10 @@ static void TryConstructorInitialization(Sema &S,
Expr **Args, unsigned NumArgs,
QualType DestType,
InitializationSequence &Sequence) {
- Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
+ if (Kind.getKind() == InitializationKind::IK_Copy)
+ Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion);
+ else
+ Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
@@ -2512,7 +2470,7 @@ static void TryConstructorInitialization(Sema &S,
Constructor = cast<CXXConstructorDecl>(*Con);
if (!Constructor->isInvalidDecl() &&
- Constructor->isConvertingConstructor(AllowExplicit)) {
+ (AllowExplicit || !Constructor->isExplicit())) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
Args, NumArgs, CandidateSet);
@@ -2535,9 +2493,13 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
- Sequence.AddConstructorInitializationStep(
+ if (Kind.getKind() == InitializationKind::IK_Copy) {
+ Sequence.AddUserConversionStep(Best->Function, DestType);
+ } else {
+ Sequence.AddConstructorInitializationStep(
cast<CXXConstructorDecl>(Best->Function),
- DestType);
+ DestType);
+ }
}
/// \brief Attempt value initialization (C++ [dcl.init]p7).
@@ -2548,7 +2510,7 @@ static void TryValueInitialization(Sema &S,
// C++ [dcl.init]p5:
//
// To value-initialize an object of type T means:
- QualType T = Entity.getType().getType();
+ QualType T = Entity.getType();
// -- if T is an array type, then each element is value-initialized;
while (const ArrayType *AT = S.Context.getAsArrayType(T))
@@ -2566,15 +2528,58 @@ static void TryValueInitialization(Sema &S,
if (ClassDecl->hasUserDeclaredConstructor())
return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
- // FIXME: non-union class type w/ non-trivial default constructor gets
- // zero-initialized, then constructor gets called.
+ // -- if T is a (possibly cv-qualified) non-union class type
+ // without a user-provided constructor, then the object is
+ // zero-initialized and, if T’s implicitly-declared default
+ // constructor is non-trivial, that constructor is called.
+ if ((ClassDecl->getTagKind() == TagDecl::TK_class ||
+ ClassDecl->getTagKind() == TagDecl::TK_struct) &&
+ !ClassDecl->hasTrivialConstructor()) {
+ Sequence.AddZeroInitializationStep(Entity.getType());
+ return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
+ }
}
}
- Sequence.AddZeroInitializationStep(Entity.getType().getType());
+ Sequence.AddZeroInitializationStep(Entity.getType());
Sequence.setSequenceKind(InitializationSequence::ZeroInitialization);
}
+/// \brief Attempt default initialization (C++ [dcl.init]p6).
+static void TryDefaultInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitializationSequence &Sequence) {
+ assert(Kind.getKind() == InitializationKind::IK_Default);
+
+ // C++ [dcl.init]p6:
+ // To default-initialize an object of type T means:
+ // - if T is an array type, each element is default-initialized;
+ QualType DestType = Entity.getType();
+ while (const ArrayType *Array = S.Context.getAsArrayType(DestType))
+ DestType = Array->getElementType();
+
+ // - if T is a (possibly cv-qualified) class type (Clause 9), the default
+ // constructor for T is called (and the initialization is ill-formed if
+ // T has no accessible default constructor);
+ if (DestType->isRecordType()) {
+ // FIXME: If a program calls for the default initialization of an object of
+ // a const-qualified type T, T shall be a class type with a user-provided
+ // default constructor.
+ return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType,
+ Sequence);
+ }
+
+ // - otherwise, no initialization is performed.
+ Sequence.setSequenceKind(InitializationSequence::NoInitialization);
+
+ // If a program calls for the default initialization of an object of
+ // a const-qualified type T, T shall be a class type with a user-provided
+ // default constructor.
+ if (DestType.isConstQualified())
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+}
+
/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
/// which enumerates all conversion functions and performs overload resolution
/// to select the best.
@@ -2585,7 +2590,7 @@ static void TryUserDefinedConversion(Sema &S,
InitializationSequence &Sequence) {
Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion);
- QualType DestType = Entity.getType().getType();
+ QualType DestType = Entity.getType();
assert(!DestType->isReferenceType() && "References are handled elsewhere");
QualType SourceType = Initializer->getType();
assert((DestType->isRecordType() || SourceType->isRecordType()) &&
@@ -2632,43 +2637,49 @@ static void TryUserDefinedConversion(Sema &S,
}
}
}
-
+
+ SourceLocation DeclLoc = Initializer->getLocStart();
+
if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
// The type we're converting from is a class type, enumerate its conversion
// functions.
- CXXRecordDecl *SourceRecordDecl
- = cast<CXXRecordDecl>(SourceRecordType->getDecl());
-
- const UnresolvedSet *Conversions
- = SourceRecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSet::iterator I = Conversions->begin(),
- E = Conversions->end();
- I != E; ++I) {
- NamedDecl *D = *I;
- CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
- if (isa<UsingShadowDecl>(D))
- D = cast<UsingShadowDecl>(D)->getTargetDecl();
-
- FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
- CXXConversionDecl *Conv;
- if (ConvTemplate)
- Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
- else
- Conv = cast<CXXConversionDecl>(*I);
+
+ // We can only enumerate the conversion functions for a complete type; if
+ // the type isn't complete, simply skip this step.
+ if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) {
+ CXXRecordDecl *SourceRecordDecl
+ = cast<CXXRecordDecl>(SourceRecordType->getDecl());
- if (AllowExplicit || !Conv->isExplicit()) {
+ const UnresolvedSet *Conversions
+ = SourceRecordDecl->getVisibleConversionFunctions();
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end();
+ I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+ CXXConversionDecl *Conv;
if (ConvTemplate)
- S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, Initializer,
- DestType, CandidateSet);
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
- S.AddConversionCandidate(Conv, ActingDC, Initializer, DestType,
- CandidateSet);
+ Conv = cast<CXXConversionDecl>(*I);
+
+ if (AllowExplicit || !Conv->isExplicit()) {
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, ActingDC,
+ Initializer, DestType,
+ CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, ActingDC, Initializer, DestType,
+ CandidateSet);
+ }
}
}
}
- SourceLocation DeclLoc = Initializer->getLocStart();
-
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
@@ -2711,7 +2722,7 @@ static void TryImplicitConversion(Sema &S,
Expr *Initializer,
InitializationSequence &Sequence) {
ImplicitConversionSequence ICS
- = S.TryImplicitConversion(Initializer, Entity.getType().getType(),
+ = S.TryImplicitConversion(Initializer, Entity.getType(),
/*SuppressUserConversions=*/true,
/*AllowExplicit=*/false,
/*ForceRValue=*/false,
@@ -2723,7 +2734,7 @@ static void TryImplicitConversion(Sema &S,
return;
}
- Sequence.AddConversionSequenceStep(ICS, Entity.getType().getType());
+ Sequence.AddConversionSequenceStep(ICS, Entity.getType());
}
InitializationSequence::InitializationSequence(Sema &S,
@@ -2739,7 +2750,7 @@ InitializationSequence::InitializationSequence(Sema &S,
// type is the type of the initializer expression. The source type is not
// defined when the initializer is a braced-init-list or when it is a
// parenthesized list of expressions.
- QualType DestType = Entity.getType().getType();
+ QualType DestType = Entity.getType();
if (DestType->isDependentType() ||
Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
@@ -2749,7 +2760,7 @@ InitializationSequence::InitializationSequence(Sema &S,
QualType SourceType;
Expr *Initializer = 0;
- if (Kind.getKind() == InitializationKind::IK_Copy) {
+ if (NumArgs == 1) {
Initializer = Args[0];
if (!isa<InitListExpr>(Initializer))
SourceType = Initializer->getType();
@@ -2785,11 +2796,18 @@ InitializationSequence::InitializationSequence(Sema &S,
}
// - If the initializer is (), the object is value-initialized.
- if (Kind.getKind() == InitializationKind::IK_Value) {
+ if (Kind.getKind() == InitializationKind::IK_Value ||
+ (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
TryValueInitialization(S, Entity, Kind, *this);
return;
}
+ // Handle default initialization.
+ if (Kind.getKind() == InitializationKind::IK_Default){
+ TryDefaultInitialization(S, Entity, Kind, *this);
+ return;
+ }
+
// - Otherwise, if the destination type is an array, the program is
// ill-formed.
if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
@@ -2800,6 +2818,13 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
+
+ // Handle initialization in C
+ if (!S.getLangOptions().CPlusPlus) {
+ setSequenceKind(CAssignment);
+ AddCAssignmentStep(DestType);
+ return;
+ }
// - If the destination type is a (possibly cv-qualified) class type:
if (DestType->isRecordType()) {
@@ -2812,7 +2837,7 @@ InitializationSequence::InitializationSequence(Sema &S,
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
S.IsDerivedFrom(SourceType, DestType))))
TryConstructorInitialization(S, Entity, Kind, Args, NumArgs,
- Entity.getType().getType(), *this);
+ Entity.getType(), *this);
// - Otherwise (i.e., for the remaining copy-initialization cases),
// user-defined conversion sequences that can convert from the source
// type to the destination type or (when a conversion function is
@@ -2824,9 +2849,15 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
+ if (NumArgs > 1) {
+ SetFailed(FK_TooManyInitsForScalar);
+ return;
+ }
+ assert(NumArgs == 1 && "Zero-argument case handled above");
+
// - Otherwise, if the source type is a (possibly cv-qualified) class
// type, conversion functions are considered.
- if (SourceType->isRecordType()) {
+ if (!SourceType.isNull() && SourceType->isRecordType()) {
TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
return;
}
@@ -2836,6 +2867,7 @@ InitializationSequence::InitializationSequence(Sema &S,
// conversions (Clause 4) will be used, if necessary, to convert the
// initializer expression to the cv-unqualified version of the
// destination type; no user-defined conversions are considered.
+ setSequenceKind(StandardConversion);
TryImplicitConversion(S, Entity, Kind, Initializer, *this);
}
@@ -2849,6 +2881,158 @@ InitializationSequence::~InitializationSequence() {
//===----------------------------------------------------------------------===//
// Perform initialization
//===----------------------------------------------------------------------===//
+static Sema::AssignmentAction
+getAssignmentAction(const InitializedEntity &Entity) {
+ switch(Entity.getKind()) {
+ case InitializedEntity::EK_Variable:
+ case InitializedEntity::EK_New:
+ return Sema::AA_Initializing;
+
+ case InitializedEntity::EK_Parameter:
+ // FIXME: Can we tell when we're sending vs. passing?
+ return Sema::AA_Passing;
+
+ case InitializedEntity::EK_Result:
+ return Sema::AA_Returning;
+
+ case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_Base:
+ llvm_unreachable("No assignment action for C++-specific initialization");
+ break;
+
+ case InitializedEntity::EK_Temporary:
+ // FIXME: Can we tell apart casting vs. converting?
+ return Sema::AA_Casting;
+
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ArrayOrVectorElement:
+ return Sema::AA_Initializing;
+ }
+
+ return Sema::AA_Converting;
+}
+
+static bool shouldBindAsTemporary(const InitializedEntity &Entity,
+ bool IsCopy) {
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_Exception:
+ return !IsCopy;
+
+ case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Variable:
+ case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ArrayOrVectorElement:
+ return false;
+
+ case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Temporary:
+ return true;
+ }
+
+ llvm_unreachable("missed an InitializedEntity kind?");
+}
+
+/// \brief If we need to perform an additional copy of the initialized object
+/// for this kind of entity (e.g., the result of a function or an object being
+/// thrown), make the copy.
+static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Sema::OwningExprResult CurInit) {
+ SourceLocation Loc;
+
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_Result:
+ if (Entity.getType()->isReferenceType())
+ return move(CurInit);
+ Loc = Entity.getReturnLoc();
+ break;
+
+ case InitializedEntity::EK_Exception:
+ Loc = Entity.getThrowLoc();
+ break;
+
+ case InitializedEntity::EK_Variable:
+ if (Entity.getType()->isReferenceType() ||
+ Kind.getKind() != InitializationKind::IK_Copy)
+ return move(CurInit);
+ Loc = Entity.getDecl()->getLocation();
+ break;
+
+ case InitializedEntity::EK_Parameter:
+ // FIXME: Do we need this initialization for a parameter?
+ return move(CurInit);
+
+ case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ArrayOrVectorElement:
+ // We don't need to copy for any of these initialized entities.
+ return move(CurInit);
+ }
+
+ Expr *CurInitExpr = (Expr *)CurInit.get();
+ CXXRecordDecl *Class = 0;
+ if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
+ Class = cast<CXXRecordDecl>(Record->getDecl());
+ if (!Class)
+ return move(CurInit);
+
+ // Perform overload resolution using the class's copy constructors.
+ DeclarationName ConstructorName
+ = S.Context.DeclarationNames.getCXXConstructorName(
+ S.Context.getCanonicalType(S.Context.getTypeDeclType(Class)));
+ DeclContext::lookup_iterator Con, ConEnd;
+ OverloadCandidateSet CandidateSet;
+ for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con);
+ if (!Constructor || Constructor->isInvalidDecl() ||
+ !Constructor->isCopyConstructor())
+ continue;
+
+ S.AddOverloadCandidate(Constructor, &CurInitExpr, 1, CandidateSet);
+ }
+
+ OverloadCandidateSet::iterator Best;
+ switch (S.BestViableFunction(CandidateSet, Loc, Best)) {
+ case OR_Success:
+ break;
+
+ case OR_No_Viable_Function:
+ S.Diag(Loc, diag::err_temp_copy_no_viable)
+ << (int)Entity.getKind() << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange();
+ S.PrintOverloadCandidates(CandidateSet, false);
+ return S.ExprError();
+
+ case OR_Ambiguous:
+ S.Diag(Loc, diag::err_temp_copy_ambiguous)
+ << (int)Entity.getKind() << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange();
+ S.PrintOverloadCandidates(CandidateSet, true);
+ return S.ExprError();
+
+ case OR_Deleted:
+ S.Diag(Loc, diag::err_temp_copy_deleted)
+ << (int)Entity.getKind() << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange();
+ S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+ << Best->Function->isDeleted();
+ return S.ExprError();
+ }
+
+ CurInit.release();
+ return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(),
+ cast<CXXConstructorDecl>(Best->Function),
+ /*Elidable=*/true,
+ Sema::MultiExprArg(S,
+ (void**)&CurInitExpr, 1));
+}
Action::OwningExprResult
InitializationSequence::Perform(Sema &S,
@@ -2866,9 +3050,9 @@ InitializationSequence::Perform(Sema &S,
// If the declaration is a non-dependent, incomplete array type
// that has an initializer, then its type will be completed once
// the initializer is instantiated.
- if (ResultType && !Entity.getType().getType()->isDependentType() &&
+ if (ResultType && !Entity.getType()->isDependentType() &&
Args.size() == 1) {
- QualType DeclType = Entity.getType().getType();
+ QualType DeclType = Entity.getType();
if (const IncompleteArrayType *ArrayT
= S.Context.getAsIncompleteArrayType(DeclType)) {
// FIXME: We don't currently have the ability to accurately
@@ -2880,11 +3064,15 @@ InitializationSequence::Perform(Sema &S,
// bound.
if (isa<InitListExpr>((Expr *)Args.get()[0])) {
SourceRange Brackets;
+
// Scavange the location of the brackets from the entity, if we can.
- if (isa<IncompleteArrayTypeLoc>(Entity.getType())) {
- IncompleteArrayTypeLoc ArrayLoc
- = cast<IncompleteArrayTypeLoc>(Entity.getType());
- Brackets = ArrayLoc.getBracketsRange();
+ if (DeclaratorDecl *DD = Entity.getDecl()) {
+ if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
+ TypeLoc TL = TInfo->getTypeLoc();
+ if (IncompleteArrayTypeLoc *ArrayLoc
+ = dyn_cast<IncompleteArrayTypeLoc>(&TL))
+ Brackets = ArrayLoc->getBracketsRange();
+ }
}
*ResultType
@@ -2898,7 +3086,7 @@ InitializationSequence::Perform(Sema &S,
}
}
- if (Kind.getKind() == InitializationKind::IK_Copy)
+ if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast())
return Sema::OwningExprResult(S, Args.release()[0]);
unsigned NumArgs = Args.size();
@@ -2909,34 +3097,58 @@ InitializationSequence::Perform(Sema &S,
SourceLocation()));
}
- QualType DestType = Entity.getType().getType().getNonReferenceType();
+ if (SequenceKind == NoInitialization)
+ return S.Owned((Expr *)0);
+
+ QualType DestType = Entity.getType().getNonReferenceType();
+ // FIXME: Ugly hack around the fact that Entity.getType() is not
+ // the same as Entity.getDecl()->getType() in cases involving type merging,
+ // and we want latter when it makes sense.
if (ResultType)
- *ResultType = Entity.getType().getType();
-
- Sema::OwningExprResult CurInit(S);
- // For copy initialization and any other initialization forms that
- // only have a single initializer, we start with the (only)
- // initializer we have.
- // FIXME: DPG is not happy about this. There's confusion regarding whether
- // we're supposed to start the conversion from the solitary initializer or
- // from the set of arguments.
- if (Kind.getKind() == InitializationKind::IK_Copy ||
- SequenceKind != ConstructorInitialization) {
+ *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
+ Entity.getType();
+
+ Sema::OwningExprResult CurInit = S.Owned((Expr *)0);
+
+ assert(!Steps.empty() && "Cannot have an empty initialization sequence");
+
+ // For initialization steps that start with a single initializer,
+ // grab the only argument out the Args and place it into the "current"
+ // initializer.
+ switch (Steps.front().Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseLValue:
+ case SK_BindReference:
+ case SK_BindReferenceToTemporary:
+ case SK_UserConversion:
+ case SK_QualificationConversionLValue:
+ case SK_QualificationConversionRValue:
+ case SK_ConversionSequence:
+ case SK_ListInitialization:
+ case SK_CAssignment:
+ case SK_StringInit:
assert(Args.size() == 1);
- CurInit = Sema::OwningExprResult(S, Args.release()[0]);
+ CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain());
if (CurInit.isInvalid())
return S.ExprError();
+ break;
+
+ case SK_ConstructorInitialization:
+ case SK_ZeroInitialization:
+ break;
}
// Walk through the computed steps for the initialization sequence,
// performing the specified conversions along the way.
+ bool ConstructorInitRequiresZeroInit = false;
for (step_iterator Step = step_begin(), StepEnd = step_end();
Step != StepEnd; ++Step) {
if (CurInit.isInvalid())
return S.ExprError();
Expr *CurInitExpr = (Expr *)CurInit.get();
- QualType SourceType = CurInitExpr->getType();
+ QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType();
switch (Step->Kind) {
case SK_ResolveAddressOfOverloadedFunction:
@@ -2969,7 +3181,7 @@ InitializationSequence::Perform(Sema &S,
if (FieldDecl *BitField = CurInitExpr->getBitField()) {
// References cannot bind to bit fields (C++ [dcl.init.ref]p5).
S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
- << Entity.getType().getType().isVolatileQualified()
+ << Entity.getType().isVolatileQualified()
<< BitField->getDeclName()
<< CurInitExpr->getSourceRange();
S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
@@ -2996,6 +3208,7 @@ InitializationSequence::Perform(Sema &S,
// We have a user-defined conversion that invokes either a constructor
// or a conversion function.
CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
+ bool IsCopy = false;
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(Step->Function)) {
// Build a call to the selected constructor.
@@ -3019,10 +3232,14 @@ InitializationSequence::Perform(Sema &S,
return S.ExprError();
CastKind = CastExpr::CK_ConstructorConversion;
+ QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
+ if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
+ S.IsDerivedFrom(SourceType, Class))
+ IsCopy = true;
} else {
// Build a call to the conversion function.
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Step->Function);
-
+
// FIXME: Should we move this initialization into a separate
// derived-to-base conversion? I believe the answer is "no", because
// we don't want to turn off access control here for c-style casts.
@@ -3041,12 +3258,17 @@ InitializationSequence::Perform(Sema &S,
CastKind = CastExpr::CK_UserDefinedConversion;
}
- CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+ if (shouldBindAsTemporary(Entity, IsCopy))
+ CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+
CurInitExpr = CurInit.takeAs<Expr>();
CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(),
CastKind,
CurInitExpr,
- false));
+ false));
+
+ if (!IsCopy)
+ CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
break;
}
@@ -3061,7 +3283,7 @@ InitializationSequence::Perform(Sema &S,
break;
case SK_ConversionSequence:
- if (S.PerformImplicitConversion(CurInitExpr, Step->Type, "converting",
+ if (S.PerformImplicitConversion(CurInitExpr, Step->Type, Sema::AA_Converting,
false, false, *Step->ICS))
return S.ExprError();
@@ -3072,7 +3294,7 @@ InitializationSequence::Perform(Sema &S,
case SK_ListInitialization: {
InitListExpr *InitList = cast<InitListExpr>(CurInitExpr);
QualType Ty = Step->Type;
- if (S.CheckInitList(InitList, ResultType? *ResultType : Ty))
+ if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty))
return S.ExprError();
CurInit.release();
@@ -3095,22 +3317,68 @@ InitializationSequence::Perform(Sema &S,
return S.ExprError();
// Build the an expression that constructs a temporary.
- CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
- move_arg(ConstructorArgs));
+ CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ Constructor,
+ move_arg(ConstructorArgs),
+ ConstructorInitRequiresZeroInit);
if (CurInit.isInvalid())
return S.ExprError();
-
- CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+
+ bool Elidable
+ = cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable();
+ if (shouldBindAsTemporary(Entity, Elidable))
+ CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+
+ if (!Elidable)
+ CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
break;
}
case SK_ZeroInitialization: {
- if (Kind.getKind() == InitializationKind::IK_Value)
+ step_iterator NextStep = Step;
+ ++NextStep;
+ if (NextStep != StepEnd &&
+ NextStep->Kind == SK_ConstructorInitialization) {
+ // The need for zero-initialization is recorded directly into
+ // the call to the object's constructor within the next step.
+ ConstructorInitRequiresZeroInit = true;
+ } else if (Kind.getKind() == InitializationKind::IK_Value &&
+ S.getLangOptions().CPlusPlus &&
+ !Kind.isImplicitValueInit()) {
CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type,
Kind.getRange().getBegin(),
Kind.getRange().getEnd()));
- else
+ } else {
CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
+ }
+ break;
+ }
+
+ case SK_CAssignment: {
+ QualType SourceType = CurInitExpr->getType();
+ Sema::AssignConvertType ConvTy =
+ S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr);
+
+ // If this is a call, allow conversion to a transparent union.
+ if (ConvTy != Sema::Compatible &&
+ Entity.getKind() == InitializedEntity::EK_Parameter &&
+ S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExpr)
+ == Sema::Compatible)
+ ConvTy = Sema::Compatible;
+
+ if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
+ Step->Type, SourceType,
+ CurInitExpr, getAssignmentAction(Entity)))
+ return S.ExprError();
+
+ CurInit.release();
+ CurInit = S.Owned(CurInitExpr);
+ break;
+ }
+
+ case SK_StringInit: {
+ QualType Ty = Step->Type;
+ CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
break;
}
}
@@ -3129,7 +3397,7 @@ bool InitializationSequence::Diagnose(Sema &S,
if (SequenceKind != FailedSequence)
return false;
- QualType DestType = Entity.getType().getType();
+ QualType DestType = Entity.getType();
switch (Failure) {
case FK_TooManyInitsForReference:
S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
@@ -3152,9 +3420,15 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_UserConversionOverloadFailed:
switch (FailedOverloadResult) {
case OR_Ambiguous:
- S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
- << Args[0]->getType() << DestType.getNonReferenceType()
- << Args[0]->getSourceRange();
+ if (Failure == FK_UserConversionOverloadFailed)
+ S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
+ << Args[0]->getType() << DestType
+ << Args[0]->getSourceRange();
+ else
+ S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
+ << DestType << Args[0]->getType()
+ << Args[0]->getSourceRange();
+
S.PrintOverloadCandidates(FailedCandidateSet, true);
break;
@@ -3220,7 +3494,8 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
case FK_ConversionFailed:
- S.Diag(Kind.getLocation(), diag::err_cannot_initialize_decl_noname)
+ S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
+ << (int)Entity.getKind()
<< DestType
<< (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
<< Args[0]->getType()
@@ -3228,12 +3503,16 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
case FK_TooManyInitsForScalar: {
- InitListExpr *InitList = cast<InitListExpr>(Args[0]);
+ SourceRange R;
+
+ if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
+ R = SourceRange(InitList->getInit(1)->getLocStart(),
+ InitList->getLocEnd());
+ else
+ R = SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
S.Diag(Kind.getLocation(), diag::err_excess_initializers)
- << /*scalar=*/2
- << SourceRange(InitList->getInit(1)->getLocStart(),
- InitList->getLocEnd());
+ << /*scalar=*/2 << R;
break;
}
@@ -3290,7 +3569,36 @@ bool InitializationSequence::Diagnose(Sema &S,
}
break;
}
+
+ case FK_DefaultInitOfConst:
+ S.Diag(Kind.getLocation(), diag::err_default_init_const)
+ << DestType;
+ break;
}
return true;
}
+
+//===----------------------------------------------------------------------===//
+// Initialization helper functions
+//===----------------------------------------------------------------------===//
+Sema::OwningExprResult
+Sema::PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ OwningExprResult Init) {
+ if (Init.isInvalid())
+ return ExprError();
+
+ Expr *InitE = (Expr *)Init.get();
+ assert(InitE && "No initialization expression?");
+
+ if (EqualLoc.isInvalid())
+ EqualLoc = InitE->getLocStart();
+
+ InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(),
+ EqualLoc);
+ InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
+ Init.release();
+ return Seq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, (void**)&InitE, 1));
+}
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
index 2d4b01f..5eb819a 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -14,7 +14,7 @@
#define LLVM_CLANG_SEMA_INIT_H
#include "SemaOverload.h"
-#include "clang/AST/TypeLoc.h"
+#include "clang/AST/Type.h"
#include "clang/Parse/Action.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -47,72 +47,79 @@ public:
/// \brief The entity being initialized is an exception object that
/// is being thrown.
EK_Exception,
+ /// \brief The entity being initialized is an object (or array of
+ /// objects) allocated via new.
+ EK_New,
/// \brief The entity being initialized is a temporary object.
EK_Temporary,
/// \brief The entity being initialized is a base member subobject.
EK_Base,
/// \brief The entity being initialized is a non-static data member
/// subobject.
- EK_Member
+ EK_Member,
+ /// \brief The entity being initialized is an element of an array
+ /// or vector.
+ EK_ArrayOrVectorElement
};
private:
/// \brief The kind of entity being initialized.
EntityKind Kind;
- /// \brief The type of the object or reference being initialized along with
- /// its location information.
- TypeLoc TL;
+ /// \brief If non-NULL, the parent entity in which this
+ /// initialization occurs.
+ const InitializedEntity *Parent;
+
+ /// \brief The type of the object or reference being initialized.
+ QualType Type;
union {
/// \brief When Kind == EK_Variable, EK_Parameter, or EK_Member,
/// the VarDecl, ParmVarDecl, or FieldDecl, respectively.
DeclaratorDecl *VariableOrMember;
- /// \brief When Kind == EK_Result or EK_Exception, the location of the
- /// 'return' or 'throw' keyword, respectively. When Kind == EK_Temporary,
- /// the location where the temporary is being created.
+ /// \brief When Kind == EK_Result, EK_Exception, or EK_New, the
+ /// location of the 'return', 'throw', or 'new' keyword,
+ /// respectively. When Kind == EK_Temporary, the location where
+ /// the temporary is being created.
unsigned Location;
/// \brief When Kind == EK_Base, the base specifier that provides the
/// base class.
CXXBaseSpecifier *Base;
+
+ /// \brief When Kind = EK_ArrayOrVectorElement, the index of the
+ /// array or vector element being initialized.
+ unsigned Index;
};
InitializedEntity() { }
/// \brief Create the initialization entity for a variable.
InitializedEntity(VarDecl *Var)
- : Kind(EK_Variable),
- VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Var))
- {
- InitDeclLoc();
- }
+ : Kind(EK_Variable), Parent(0), Type(Var->getType()),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Var)) { }
/// \brief Create the initialization entity for a parameter.
InitializedEntity(ParmVarDecl *Parm)
- : Kind(EK_Parameter),
- VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Parm))
- {
- InitDeclLoc();
- }
+ : Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Parm)) { }
- /// \brief Create the initialization entity for the result of a function,
- /// throwing an object, or performing an explicit cast.
- InitializedEntity(EntityKind Kind, SourceLocation Loc, TypeLoc TL)
- : Kind(Kind), TL(TL), Location(Loc.getRawEncoding()) { }
+ /// \brief Create the initialization entity for the result of a
+ /// function, throwing an object, performing an explicit cast, or
+ /// initializing a parameter for which there is no declaration.
+ InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type)
+ : Kind(Kind), Parent(0), Type(Type), Location(Loc.getRawEncoding()) { }
/// \brief Create the initialization entity for a member subobject.
- InitializedEntity(FieldDecl *Member)
- : Kind(EK_Member),
- VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Member))
- {
- InitDeclLoc();
- }
-
- /// \brief Initialize type-location information from a declaration.
- void InitDeclLoc();
+ InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent)
+ : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Member)) { }
+ /// \brief Create the initialization entity for an array element.
+ InitializedEntity(ASTContext &Context, unsigned Index,
+ const InitializedEntity &Parent);
+
public:
/// \brief Create the initialization entity for a variable.
static InitializedEntity InitializeVariable(VarDecl *Var) {
@@ -124,38 +131,69 @@ public:
return InitializedEntity(Parm);
}
+ /// \brief Create the initialization entity for a parameter that is
+ /// only known by its type.
+ static InitializedEntity InitializeParameter(QualType Type) {
+ return InitializedEntity(EK_Parameter, SourceLocation(), Type);
+ }
+
/// \brief Create the initialization entity for the result of a function.
static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
- TypeLoc TL) {
- return InitializedEntity(EK_Result, ReturnLoc, TL);
+ QualType Type) {
+ return InitializedEntity(EK_Result, ReturnLoc, Type);
}
/// \brief Create the initialization entity for an exception object.
static InitializedEntity InitializeException(SourceLocation ThrowLoc,
- TypeLoc TL) {
- return InitializedEntity(EK_Exception, ThrowLoc, TL);
+ QualType Type) {
+ return InitializedEntity(EK_Exception, ThrowLoc, Type);
+ }
+
+ /// \brief Create the initialization entity for an object allocated via new.
+ static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) {
+ return InitializedEntity(EK_New, NewLoc, Type);
}
/// \brief Create the initialization entity for a temporary.
- static InitializedEntity InitializeTemporary(EntityKind Kind, TypeLoc TL) {
- return InitializedEntity(Kind, SourceLocation(), TL);
+ static InitializedEntity InitializeTemporary(QualType Type) {
+ return InitializedEntity(EK_Temporary, SourceLocation(), Type);
}
/// \brief Create the initialization entity for a base class subobject.
static InitializedEntity InitializeBase(ASTContext &Context,
CXXBaseSpecifier *Base);
- /// \brief Create the initialize entity for a member subobject.
- static InitializedEntity InitializeMember(FieldDecl *Member) {
- return InitializedEntity(Member);
+ /// \brief Create the initialization entity for a member subobject.
+ static InitializedEntity InitializeMember(FieldDecl *Member,
+ const InitializedEntity *Parent = 0) {
+ return InitializedEntity(Member, Parent);
}
+ /// \brief Create the initialization entity for an array element.
+ static InitializedEntity InitializeElement(ASTContext &Context,
+ unsigned Index,
+ const InitializedEntity &Parent) {
+ return InitializedEntity(Context, Index, Parent);
+ }
+
/// \brief Determine the kind of initialization.
EntityKind getKind() const { return Kind; }
+ /// \brief Retrieve the parent of the entity being initialized, when
+ /// the initialization itself is occuring within the context of a
+ /// larger initialization.
+ const InitializedEntity *getParent() const { return Parent; }
+
/// \brief Retrieve type being initialized.
- TypeLoc getType() const { return TL; }
+ QualType getType() const { return Type; }
+ /// \brief Retrieve the name of the entity being initialized.
+ DeclarationName getName() const;
+
+ /// \brief Retrieve the variable, parameter, or field being
+ /// initialized.
+ DeclaratorDecl *getDecl() const;
+
/// \brief Determine the location of the 'return' keyword when initializing
/// the result of a function call.
SourceLocation getReturnLoc() const {
@@ -169,6 +207,13 @@ public:
assert(getKind() == EK_Exception && "No 'throw' location!");
return SourceLocation::getFromRawEncoding(Location);
}
+
+ /// \brief If this is already the initializer for an array or vector
+ /// element, sets the element index.
+ void setElementIndex(unsigned Index) {
+ assert(getKind() == EK_ArrayOrVectorElement);
+ this->Index = Index;
+ }
};
/// \brief Describes the kind of initialization being performed, along with
@@ -191,6 +236,7 @@ private:
SIK_Copy = IK_Copy, ///< Copy initialization
SIK_Default = IK_Default, ///< Default initialization
SIK_Value = IK_Value, ///< Value initialization
+ SIK_ImplicitValue, ///< Implicit value initialization
SIK_DirectCast, ///< Direct initialization due to a cast
/// \brief Direct initialization due to a C-style or functional cast.
SIK_DirectCStyleOrFunctionalCast
@@ -242,15 +288,19 @@ public:
/// \brief Create a value initialization.
static InitializationKind CreateValue(SourceLocation InitLoc,
SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return InitializationKind(SIK_Value, InitLoc, LParenLoc, RParenLoc);
+ SourceLocation RParenLoc,
+ bool isImplicit = false) {
+ return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value,
+ InitLoc, LParenLoc, RParenLoc);
}
/// \brief Determine the initialization kind.
InitKind getKind() const {
- if (Kind > SIK_Value)
+ if (Kind > SIK_ImplicitValue)
return IK_Direct;
-
+ if (Kind == SIK_ImplicitValue)
+ return IK_Value;
+
return (InitKind)Kind;
}
@@ -263,7 +313,12 @@ public:
bool isCStyleOrFunctionalCast() const {
return Kind == SIK_DirectCStyleOrFunctionalCast;
}
-
+
+ /// \brief Determine whether this initialization is an implicit
+ /// value-initialization, e.g., as occurs during aggregate
+ /// initialization.
+ bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; }
+
/// \brief Retrieve the location at which initialization is occurring.
SourceLocation getLocation() const { return Locations[0]; }
@@ -319,7 +374,19 @@ public:
ListInitialization,
/// \brief Zero-initialization.
- ZeroInitialization
+ ZeroInitialization,
+
+ /// \brief No initialization required.
+ NoInitialization,
+
+ /// \brief Standard conversion sequence.
+ StandardConversion,
+
+ /// \brief C conversion sequence.
+ CAssignment,
+
+ /// \brief String initialization
+ StringInit
};
/// \brief Describes the kind of a particular step in an initialization
@@ -350,7 +417,11 @@ public:
/// \brief Perform initialization via a constructor.
SK_ConstructorInitialization,
/// \brief Zero-initialize the object
- SK_ZeroInitialization
+ SK_ZeroInitialization,
+ /// \brief C assignment
+ SK_CAssignment,
+ /// \brief Initialization by string
+ SK_StringInit
};
/// \brief A single step in the initialization sequence.
@@ -420,7 +491,9 @@ public:
/// \brief Overloading for a user-defined conversion failed.
FK_UserConversionOverloadFailed,
/// \brief Overloaded for initialization by constructor failed.
- FK_ConstructorOverloadFailed
+ FK_ConstructorOverloadFailed,
+ /// \brief Default-initialization of a 'const' object.
+ FK_DefaultInitOfConst
};
private:
@@ -551,6 +624,16 @@ public:
/// \brief Add a zero-initialization step.
void AddZeroInitializationStep(QualType T);
+ /// \brief Add a C assignment step.
+ //
+ // FIXME: It isn't clear whether this should ever be needed;
+ // ideally, we would handle everything needed in C in the common
+ // path. However, that isn't the case yet.
+ void AddCAssignmentStep(QualType T);
+
+ /// \brief Add a string init step.
+ void AddStringInitStep(QualType T);
+
/// \brief Note that this initialization sequence failed.
void SetFailed(FailureKind Failure) {
SequenceKind = FailedSequence;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 724e2fc..1419ceb 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -27,6 +27,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/ErrorHandling.h"
+#include <list>
#include <set>
#include <vector>
#include <iterator>
@@ -192,23 +193,83 @@ namespace {
};
}
+static bool IsAcceptableIDNS(NamedDecl *D, unsigned IDNS) {
+ return D->isInIdentifierNamespace(IDNS);
+}
+
+static bool IsAcceptableOperatorName(NamedDecl *D, unsigned IDNS) {
+ return D->isInIdentifierNamespace(IDNS) &&
+ !D->getDeclContext()->isRecord();
+}
+
+static bool IsAcceptableNestedNameSpecifierName(NamedDecl *D, unsigned IDNS) {
+ // This lookup ignores everything that isn't a type.
+
+ // This is a fast check for the far most common case.
+ if (D->isInIdentifierNamespace(Decl::IDNS_Tag))
+ return true;
+
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ return isa<TypeDecl>(D);
+}
+
+static bool IsAcceptableNamespaceName(NamedDecl *D, unsigned IDNS) {
+ // We don't need to look through using decls here because
+ // using decls aren't allowed to name namespaces.
+
+ return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D);
+}
+
+/// Gets the default result filter for the given lookup.
+static inline
+LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) {
+ switch (NameKind) {
+ case Sema::LookupOrdinaryName:
+ case Sema::LookupTagName:
+ case Sema::LookupMemberName:
+ case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
+ case Sema::LookupUsingDeclName:
+ case Sema::LookupObjCProtocolName:
+ case Sema::LookupObjCImplementationName:
+ return &IsAcceptableIDNS;
+
+ case Sema::LookupOperatorName:
+ return &IsAcceptableOperatorName;
+
+ case Sema::LookupNestedNameSpecifierName:
+ return &IsAcceptableNestedNameSpecifierName;
+
+ case Sema::LookupNamespaceName:
+ return &IsAcceptableNamespaceName;
+ }
+
+ llvm_unreachable("unkknown lookup kind");
+ return 0;
+}
+
// Retrieve the set of identifier namespaces that correspond to a
// specific kind of name lookup.
-inline unsigned
-getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
- bool CPlusPlus) {
+static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
+ bool CPlusPlus,
+ bool Redeclaration) {
unsigned IDNS = 0;
switch (NameKind) {
case Sema::LookupOrdinaryName:
case Sema::LookupOperatorName:
case Sema::LookupRedeclarationWithLinkage:
IDNS = Decl::IDNS_Ordinary;
- if (CPlusPlus)
+ if (CPlusPlus) {
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
+ if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
+ }
break;
case Sema::LookupTagName:
IDNS = Decl::IDNS_Tag;
+ if (CPlusPlus && Redeclaration)
+ IDNS |= Decl::IDNS_TagFriend;
break;
case Sema::LookupMemberName:
@@ -238,6 +299,13 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
return IDNS;
}
+void LookupResult::configure() {
+ IDNS = getIDNS(LookupKind,
+ SemaRef.getLangOptions().CPlusPlus,
+ isForRedeclaration());
+ IsAcceptableFn = getResultFilter(LookupKind);
+}
+
// Necessary because CXXBasePaths is not complete in Sema.h
void LookupResult::deletePaths(CXXBasePaths *Paths) {
delete Paths;
@@ -377,8 +445,7 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I)
- if (Sema::isAcceptableLookupResult(*I, R.getLookupKind(),
- R.getIdentifierNamespace()))
+ if (R.isAcceptableDecl(*I))
R.addDecl(*I), Found = true;
return Found;
@@ -424,19 +491,7 @@ static DeclContext *findOuterContext(Scope *S) {
}
bool Sema::CppLookupName(LookupResult &R, Scope *S) {
- assert(getLangOptions().CPlusPlus &&
- "Can perform only C++ lookup");
- LookupNameKind NameKind = R.getLookupKind();
- unsigned IDNS
- = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true);
-
- // If we're testing for redeclarations, also look in the friend namespaces.
- if (R.isForRedeclaration()) {
- if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend;
- if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend;
- }
-
- R.setIdentifierNamespace(IDNS);
+ assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup");
DeclarationName Name = R.getLookupName();
@@ -467,7 +522,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
- if (isAcceptableLookupResult(*I, NameKind, IDNS)) {
+ if (R.isAcceptableDecl(*I)) {
Found = true;
R.addDecl(*I);
}
@@ -531,7 +586,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
- if (isAcceptableLookupResult(*I, NameKind, IDNS)) {
+ if (R.isAcceptableDecl(*I)) {
// We found something. Look for anything else in our scope
// with this same name and in an acceptable identifier
// namespace, so that we can construct an overload set if we
@@ -597,47 +652,18 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (!getLangOptions().CPlusPlus) {
// Unqualified name lookup in C/Objective-C is purely lexical, so
// search in the declarations attached to the name.
- unsigned IDNS = 0;
- switch (NameKind) {
- case Sema::LookupOrdinaryName:
- IDNS = Decl::IDNS_Ordinary;
- break;
- case Sema::LookupTagName:
- IDNS = Decl::IDNS_Tag;
- break;
-
- case Sema::LookupMemberName:
- IDNS = Decl::IDNS_Member;
- break;
-
- case Sema::LookupOperatorName:
- case Sema::LookupNestedNameSpecifierName:
- case Sema::LookupNamespaceName:
- case Sema::LookupUsingDeclName:
- assert(false && "C does not perform these kinds of name lookup");
- break;
-
- case Sema::LookupRedeclarationWithLinkage:
+ if (NameKind == Sema::LookupRedeclarationWithLinkage) {
// Find the nearest non-transparent declaration scope.
while (!(S->getFlags() & Scope::DeclScope) ||
(S->getEntity() &&
static_cast<DeclContext *>(S->getEntity())
->isTransparentContext()))
S = S->getParent();
- IDNS = Decl::IDNS_Ordinary;
- break;
-
- case Sema::LookupObjCProtocolName:
- IDNS = Decl::IDNS_ObjCProtocol;
- break;
-
- case Sema::LookupObjCImplementationName:
- IDNS = Decl::IDNS_ObjCImplementation;
- break;
-
}
+ unsigned IDNS = R.getIdentifierNamespace();
+
// Scan up the scope chain looking for a decl that matches this
// identifier that is in the appropriate namespace. This search
// should not take long, as shadowing of names is uncommon, and
@@ -864,17 +890,6 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) {
if (!R.getLookupName())
return false;
- // If we're performing qualified name lookup (e.g., lookup into a
- // struct), find fields as part of ordinary name lookup.
- LookupNameKind NameKind = R.getLookupKind();
- unsigned IDNS
- = getIdentifierNamespacesFromLookupNameKind(NameKind,
- getLangOptions().CPlusPlus);
- if (NameKind == LookupOrdinaryName)
- IDNS |= Decl::IDNS_Member;
-
- R.setIdentifierNamespace(IDNS);
-
// Make sure that the declaration context is complete.
assert((!isa<TagDecl>(LookupCtx) ||
LookupCtx->isDependentContext() ||
@@ -1514,15 +1529,12 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(),
E = Functions.end(); I != E; ++I) {
- FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I);
- if (!FDecl)
- FDecl = cast<FunctionTemplateDecl>(*I)->getTemplatedDecl();
+ // Look through any using declarations to find the underlying function.
+ NamedDecl *Fn = (*I)->getUnderlyingDecl();
- // Add the namespace in which this function was defined. Note
- // that, if this is a member function, we do *not* consider the
- // enclosing namespace of its class.
- DeclContext *Ctx = FDecl->getDeclContext();
- CollectNamespace(AssociatedNamespaces, Ctx);
+ FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn);
+ if (!FDecl)
+ FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl();
// Add the classes and namespaces associated with the parameter
// types and return type of this function.
@@ -1693,3 +1705,509 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
}
}
}
+
+//----------------------------------------------------------------------------
+// Search for all visible declarations.
+//----------------------------------------------------------------------------
+VisibleDeclConsumer::~VisibleDeclConsumer() { }
+
+namespace {
+
+class ShadowContextRAII;
+
+class VisibleDeclsRecord {
+public:
+ /// \brief An entry in the shadow map, which is optimized to store a
+ /// single declaration (the common case) but can also store a list
+ /// of declarations.
+ class ShadowMapEntry {
+ typedef llvm::SmallVector<NamedDecl *, 4> DeclVector;
+
+ /// \brief Contains either the solitary NamedDecl * or a vector
+ /// of declarations.
+ llvm::PointerUnion<NamedDecl *, DeclVector*> DeclOrVector;
+
+ public:
+ ShadowMapEntry() : DeclOrVector() { }
+
+ void Add(NamedDecl *ND);
+ void Destroy();
+
+ // Iteration.
+ typedef NamedDecl **iterator;
+ iterator begin();
+ iterator end();
+ };
+
+private:
+ /// \brief A mapping from declaration names to the declarations that have
+ /// this name within a particular scope.
+ typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
+
+ /// \brief A list of shadow maps, which is used to model name hiding.
+ std::list<ShadowMap> ShadowMaps;
+
+ /// \brief The declaration contexts we have already visited.
+ llvm::SmallPtrSet<DeclContext *, 8> VisitedContexts;
+
+ friend class ShadowContextRAII;
+
+public:
+ /// \brief Determine whether we have already visited this context
+ /// (and, if not, note that we are going to visit that context now).
+ bool visitedContext(DeclContext *Ctx) {
+ return !VisitedContexts.insert(Ctx);
+ }
+
+ /// \brief Determine whether the given declaration is hidden in the
+ /// current scope.
+ ///
+ /// \returns the declaration that hides the given declaration, or
+ /// NULL if no such declaration exists.
+ NamedDecl *checkHidden(NamedDecl *ND);
+
+ /// \brief Add a declaration to the current shadow map.
+ void add(NamedDecl *ND) { ShadowMaps.back()[ND->getDeclName()].Add(ND); }
+};
+
+/// \brief RAII object that records when we've entered a shadow context.
+class ShadowContextRAII {
+ VisibleDeclsRecord &Visible;
+
+ typedef VisibleDeclsRecord::ShadowMap ShadowMap;
+
+public:
+ ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) {
+ Visible.ShadowMaps.push_back(ShadowMap());
+ }
+
+ ~ShadowContextRAII() {
+ for (ShadowMap::iterator E = Visible.ShadowMaps.back().begin(),
+ EEnd = Visible.ShadowMaps.back().end();
+ E != EEnd;
+ ++E)
+ E->second.Destroy();
+
+ Visible.ShadowMaps.pop_back();
+ }
+};
+
+} // end anonymous namespace
+
+void VisibleDeclsRecord::ShadowMapEntry::Add(NamedDecl *ND) {
+ if (DeclOrVector.isNull()) {
+ // 0 - > 1 elements: just set the single element information.
+ DeclOrVector = ND;
+ return;
+ }
+
+ if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
+ // 1 -> 2 elements: create the vector of results and push in the
+ // existing declaration.
+ DeclVector *Vec = new DeclVector;
+ Vec->push_back(PrevND);
+ DeclOrVector = Vec;
+ }
+
+ // Add the new element to the end of the vector.
+ DeclOrVector.get<DeclVector*>()->push_back(ND);
+}
+
+void VisibleDeclsRecord::ShadowMapEntry::Destroy() {
+ if (DeclVector *Vec = DeclOrVector.dyn_cast<DeclVector *>()) {
+ delete Vec;
+ DeclOrVector = ((NamedDecl *)0);
+ }
+}
+
+VisibleDeclsRecord::ShadowMapEntry::iterator
+VisibleDeclsRecord::ShadowMapEntry::begin() {
+ if (DeclOrVector.isNull())
+ return 0;
+
+ if (DeclOrVector.dyn_cast<NamedDecl *>())
+ return &reinterpret_cast<NamedDecl*&>(DeclOrVector);
+
+ return DeclOrVector.get<DeclVector *>()->begin();
+}
+
+VisibleDeclsRecord::ShadowMapEntry::iterator
+VisibleDeclsRecord::ShadowMapEntry::end() {
+ if (DeclOrVector.isNull())
+ return 0;
+
+ if (DeclOrVector.dyn_cast<NamedDecl *>())
+ return &reinterpret_cast<NamedDecl*&>(DeclOrVector) + 1;
+
+ return DeclOrVector.get<DeclVector *>()->end();
+}
+
+NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
+ unsigned IDNS = ND->getIdentifierNamespace();
+ std::list<ShadowMap>::reverse_iterator SM = ShadowMaps.rbegin();
+ for (std::list<ShadowMap>::reverse_iterator SMEnd = ShadowMaps.rend();
+ SM != SMEnd; ++SM) {
+ ShadowMap::iterator Pos = SM->find(ND->getDeclName());
+ if (Pos == SM->end())
+ continue;
+
+ for (ShadowMapEntry::iterator I = Pos->second.begin(),
+ IEnd = Pos->second.end();
+ I != IEnd; ++I) {
+ // A tag declaration does not hide a non-tag declaration.
+ if ((*I)->getIdentifierNamespace() == Decl::IDNS_Tag &&
+ (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
+ Decl::IDNS_ObjCProtocol)))
+ continue;
+
+ // Protocols are in distinct namespaces from everything else.
+ if ((((*I)->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+ || (IDNS & Decl::IDNS_ObjCProtocol)) &&
+ (*I)->getIdentifierNamespace() != IDNS)
+ continue;
+
+ // We've found a declaration that hides this one.
+ return *I;
+ }
+ }
+
+ return 0;
+}
+
+static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
+ bool QualifiedNameLookup,
+ VisibleDeclConsumer &Consumer,
+ VisibleDeclsRecord &Visited) {
+ // Make sure we don't visit the same context twice.
+ if (Visited.visitedContext(Ctx->getPrimaryContext()))
+ return;
+
+ // Enumerate all of the results in this context.
+ for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
+ CurCtx = CurCtx->getNextContext()) {
+ for (DeclContext::decl_iterator D = CurCtx->decls_begin(),
+ DEnd = CurCtx->decls_end();
+ D != DEnd; ++D) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
+ if (Result.isAcceptableDecl(ND)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND));
+ Visited.add(ND);
+ }
+
+ // Visit transparent contexts inside this context.
+ if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) {
+ if (InnerCtx->isTransparentContext())
+ LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup,
+ Consumer, Visited);
+ }
+ }
+ }
+
+ // Traverse using directives for qualified name lookup.
+ if (QualifiedNameLookup) {
+ ShadowContextRAII Shadow(Visited);
+ DeclContext::udir_iterator I, E;
+ for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) {
+ LookupVisibleDecls((*I)->getNominatedNamespace(), Result,
+ QualifiedNameLookup, Consumer, Visited);
+ }
+ }
+
+ // Traverse the contexts of inherited classes.
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+ for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
+ BEnd = Record->bases_end();
+ B != BEnd; ++B) {
+ QualType BaseType = B->getType();
+
+ // Don't look into dependent bases, because name lookup can't look
+ // there anyway.
+ if (BaseType->isDependentType())
+ continue;
+
+ const RecordType *Record = BaseType->getAs<RecordType>();
+ if (!Record)
+ continue;
+
+ // FIXME: It would be nice to be able to determine whether referencing
+ // a particular member would be ambiguous. For example, given
+ //
+ // struct A { int member; };
+ // struct B { int member; };
+ // struct C : A, B { };
+ //
+ // void f(C *c) { c->### }
+ //
+ // accessing 'member' would result in an ambiguity. However, we
+ // could be smart enough to qualify the member with the base
+ // class, e.g.,
+ //
+ // c->B::member
+ //
+ // or
+ //
+ // c->A::member
+
+ // Find results in this base class (and its bases).
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup,
+ Consumer, Visited);
+ }
+ }
+
+ // FIXME: Look into base classes in Objective-C!
+}
+
+static void LookupVisibleDecls(Scope *S, LookupResult &Result,
+ UnqualUsingDirectiveSet &UDirs,
+ VisibleDeclConsumer &Consumer,
+ VisibleDeclsRecord &Visited) {
+ if (!S)
+ return;
+
+ DeclContext *Entity = 0;
+ if (S->getEntity() &&
+ !((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
+ // Look into this scope's declaration context, along with any of its
+ // parent lookup contexts (e.g., enclosing classes), up to the point
+ // where we hit the context stored in the next outer scope.
+ Entity = (DeclContext *)S->getEntity();
+ DeclContext *OuterCtx = findOuterContext(S);
+
+ for (DeclContext *Ctx = Entity; Ctx && Ctx->getPrimaryContext() != OuterCtx;
+ Ctx = Ctx->getLookupParent()) {
+ if (Ctx->isFunctionOrMethod())
+ continue;
+
+ LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false,
+ Consumer, Visited);
+ }
+ } else if (!S->getParent()) {
+ // Look into the translation unit scope. We walk through the translation
+ // unit's declaration context, because the Scope itself won't have all of
+ // the declarations if we loaded a precompiled header.
+ // FIXME: We would like the translation unit's Scope object to point to the
+ // translation unit, so we don't need this special "if" branch. However,
+ // doing so would force the normal C++ name-lookup code to look into the
+ // translation unit decl when the IdentifierInfo chains would suffice.
+ // Once we fix that problem (which is part of a more general "don't look
+ // in DeclContexts unless we have to" optimization), we can eliminate the
+ // TranslationUnit parameter entirely.
+ Entity = Result.getSema().Context.getTranslationUnitDecl();
+ LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false,
+ Consumer, Visited);
+ } else {
+ // Walk through the declarations in this Scope.
+ for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>((Decl *)((*D).get())))
+ if (Result.isAcceptableDecl(ND)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND));
+ Visited.add(ND);
+ }
+ }
+ }
+
+ if (Entity) {
+ // Lookup visible declarations in any namespaces found by using
+ // directives.
+ UnqualUsingDirectiveSet::const_iterator UI, UEnd;
+ llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
+ for (; UI != UEnd; ++UI)
+ LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()),
+ Result, /*QualifiedNameLookup=*/false, Consumer,
+ Visited);
+ }
+
+ // Lookup names in the parent scope.
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited);
+}
+
+void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer) {
+ // Determine the set of using directives available during
+ // unqualified name lookup.
+ Scope *Initial = S;
+ UnqualUsingDirectiveSet UDirs;
+ if (getLangOptions().CPlusPlus) {
+ // Find the first namespace or translation-unit scope.
+ while (S && !isNamespaceOrTranslationUnitScope(S))
+ S = S->getParent();
+
+ UDirs.visitScopeChain(Initial, S);
+ }
+ UDirs.done();
+
+ // Look for visible declarations.
+ LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+ VisibleDeclsRecord Visited;
+ ShadowContextRAII Shadow(Visited);
+ ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited);
+}
+
+void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer) {
+ LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+ VisibleDeclsRecord Visited;
+ ShadowContextRAII Shadow(Visited);
+ ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, Consumer,
+ Visited);
+}
+
+//----------------------------------------------------------------------------
+// Typo correction
+//----------------------------------------------------------------------------
+
+namespace {
+class TypoCorrectionConsumer : public VisibleDeclConsumer {
+ /// \brief The name written that is a typo in the source.
+ llvm::StringRef Typo;
+
+ /// \brief The results found that have the smallest edit distance
+ /// found (so far) with the typo name.
+ llvm::SmallVector<NamedDecl *, 4> BestResults;
+
+ /// \brief The best edit distance found so far.
+ unsigned BestEditDistance;
+
+public:
+ explicit TypoCorrectionConsumer(IdentifierInfo *Typo)
+ : Typo(Typo->getName()) { }
+
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding);
+
+ typedef llvm::SmallVector<NamedDecl *, 4>::const_iterator iterator;
+ iterator begin() const { return BestResults.begin(); }
+ iterator end() const { return BestResults.end(); }
+ bool empty() const { return BestResults.empty(); }
+
+ unsigned getBestEditDistance() const { return BestEditDistance; }
+};
+
+}
+
+void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding) {
+ // Don't consider hidden names for typo correction.
+ if (Hiding)
+ return;
+
+ // Only consider entities with identifiers for names, ignoring
+ // special names (constructors, overloaded operators, selectors,
+ // etc.).
+ IdentifierInfo *Name = ND->getIdentifier();
+ if (!Name)
+ return;
+
+ // Compute the edit distance between the typo and the name of this
+ // entity. If this edit distance is not worse than the best edit
+ // distance we've seen so far, add it to the list of results.
+ unsigned ED = Typo.edit_distance(Name->getName());
+ if (!BestResults.empty()) {
+ if (ED < BestEditDistance) {
+ // This result is better than any we've seen before; clear out
+ // the previous results.
+ BestResults.clear();
+ BestEditDistance = ED;
+ } else if (ED > BestEditDistance) {
+ // This result is worse than the best results we've seen so far;
+ // ignore it.
+ return;
+ }
+ } else
+ BestEditDistance = ED;
+
+ BestResults.push_back(ND);
+}
+
+/// \brief Try to "correct" a typo in the source code by finding
+/// visible declarations whose names are similar to the name that was
+/// present in the source code.
+///
+/// \param Res the \c LookupResult structure that contains the name
+/// that was present in the source code along with the name-lookup
+/// criteria used to search for the name. On success, this structure
+/// will contain the results of name lookup.
+///
+/// \param S the scope in which name lookup occurs.
+///
+/// \param SS the nested-name-specifier that precedes the name we're
+/// looking for, if present.
+///
+/// \param MemberContext if non-NULL, the context in which to look for
+/// a member access expression.
+///
+/// \param EnteringContext whether we're entering the context described by
+/// the nested-name-specifier SS.
+///
+/// \returns true if the typo was corrected, in which case the \p Res
+/// structure will contain the results of name lookup for the
+/// corrected name. Otherwise, returns false.
+bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
+ DeclContext *MemberContext, bool EnteringContext) {
+ // We only attempt to correct typos for identifiers.
+ IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();
+ if (!Typo)
+ return false;
+
+ // If the scope specifier itself was invalid, don't try to correct
+ // typos.
+ if (SS && SS->isInvalid())
+ return false;
+
+ // Never try to correct typos during template deduction or
+ // instantiation.
+ if (!ActiveTemplateInstantiations.empty())
+ return false;
+
+ TypoCorrectionConsumer Consumer(Typo);
+ if (MemberContext)
+ LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer);
+ else if (SS && SS->isSet()) {
+ DeclContext *DC = computeDeclContext(*SS, EnteringContext);
+ if (!DC)
+ return false;
+
+ LookupVisibleDecls(DC, Res.getLookupKind(), Consumer);
+ } else {
+ LookupVisibleDecls(S, Res.getLookupKind(), Consumer);
+ }
+
+ if (Consumer.empty())
+ return false;
+
+ // Only allow a single, closest name in the result set (it's okay to
+ // have overloads of that name, though).
+ TypoCorrectionConsumer::iterator I = Consumer.begin();
+ DeclarationName BestName = (*I)->getDeclName();
+ ++I;
+ for(TypoCorrectionConsumer::iterator IEnd = Consumer.end(); I != IEnd; ++I) {
+ if (BestName != (*I)->getDeclName())
+ return false;
+ }
+
+ // BestName is the closest viable name to what the user
+ // typed. However, to make sure that we don't pick something that's
+ // way off, make sure that the user typed at least 3 characters for
+ // each correction.
+ unsigned ED = Consumer.getBestEditDistance();
+ if (ED == 0 || (BestName.getAsIdentifierInfo()->getName().size() / ED) < 3)
+ return false;
+
+ // Perform name lookup again with the name we chose, and declare
+ // success if we found something that was not ambiguous.
+ Res.clear();
+ Res.setLookupName(BestName);
+ if (MemberContext)
+ LookupQualifiedName(Res, MemberContext);
+ else
+ LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false,
+ EnteringContext);
+
+ if (Res.isAmbiguous()) {
+ Res.suppressDiagnostics();
+ return false;
+ }
+
+ return Res.getResultKind() != LookupResult::NotFound;
+}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 561cfdb..5892081 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -13,6 +13,7 @@
#include "Sema.h"
#include "Lookup.h"
+#include "SemaInit.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/ASTContext.h"
@@ -88,7 +89,7 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
/// GetImplicitConversionName - Return the name of this kind of
/// implicit conversion.
const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
- static const char* Name[(int)ICK_Num_Conversion_Kinds] = {
+ static const char* const Name[(int)ICK_Num_Conversion_Kinds] = {
"No conversion",
"Lvalue-to-rvalue",
"Array-to-pointer",
@@ -451,7 +452,8 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
QualType FromCanon
= Context.getCanonicalType(From->getType().getUnqualifiedType());
QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
- if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
+ if (Constructor->isCopyConstructor() &&
+ (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
@@ -915,6 +917,25 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
Quals));
}
+/// BuildSimilarlyQualifiedObjCObjectPointerType - In a pointer conversion from
+/// the FromType, which is an objective-c pointer, to ToType, which may or may
+/// not have the right set of qualifiers.
+static QualType
+BuildSimilarlyQualifiedObjCObjectPointerType(QualType FromType,
+ QualType ToType,
+ ASTContext &Context) {
+ QualType CanonFromType = Context.getCanonicalType(FromType);
+ QualType CanonToType = Context.getCanonicalType(ToType);
+ Qualifiers Quals = CanonFromType.getQualifiers();
+
+ // Exact qualifier match -> return the pointer type we're converting to.
+ if (CanonToType.getLocalQualifiers() == Quals)
+ return ToType;
+
+ // Just build a canonical type that has the right qualifiers.
+ return Context.getQualifiedType(CanonToType.getLocalUnqualifiedType(), Quals);
+}
+
static bool isNullPointerConstantForConversion(Expr *Expr,
bool InOverloadResolution,
ASTContext &Context) {
@@ -992,13 +1013,20 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
return true;
}
- // Beyond this point, both types need to be pointers.
+ // Beyond this point, both types need to be pointers
+ // , including objective-c pointers.
+ QualType ToPointeeType = ToTypePtr->getPointeeType();
+ if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) {
+ ConvertedType = BuildSimilarlyQualifiedObjCObjectPointerType(FromType,
+ ToType, Context);
+ return true;
+
+ }
const PointerType *FromTypePtr = FromType->getAs<PointerType>();
if (!FromTypePtr)
return false;
QualType FromPointeeType = FromTypePtr->getPointeeType();
- QualType ToPointeeType = ToTypePtr->getPointeeType();
// An rvalue of type "pointer to cv T," where T is an object type,
// can be converted to an rvalue of type "pointer to cv void" (C++
@@ -1774,7 +1802,16 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
- if (Context.hasSameUnqualifiedType(T1, T2)) {
+ Qualifiers T1Quals, T2Quals;
+ QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+ QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+ if (UnqualT1 == UnqualT2) {
+ // If the type is an array type, promote the element qualifiers to the type
+ // for comparison.
+ if (isa<ArrayType>(T1) && T1Quals)
+ T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+ if (isa<ArrayType>(T2) && T2Quals)
+ T2 = Context.getQualifiedType(UnqualT2, T2Quals);
if (T2.isMoreQualifiedThan(T1))
return ImplicitConversionSequence::Better;
else if (T1.isMoreQualifiedThan(T2))
@@ -1807,12 +1844,22 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
+ Qualifiers T1Quals, T2Quals;
+ QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+ QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
// If the types are the same, we won't learn anything by unwrapped
// them.
- if (Context.hasSameUnqualifiedType(T1, T2))
+ if (UnqualT1 == UnqualT2)
return ImplicitConversionSequence::Indistinguishable;
+ // If the type is an array type, promote the element qualifiers to the type
+ // for comparison.
+ if (isa<ArrayType>(T1) && T1Quals)
+ T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+ if (isa<ArrayType>(T2) && T2Quals)
+ T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+
ImplicitConversionSequence::CompareKind Result
= ImplicitConversionSequence::Indistinguishable;
while (UnwrapSimilarPointerTypes(T1, T2)) {
@@ -2080,7 +2127,7 @@ Sema::TryCopyInitialization(Expr *From, QualType ToType,
/// be true when the copy may be elided (C++ 12.8p15). Overload resolution works
/// differently in C++0x for this case.
bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
- const char* Flavor, bool Elidable) {
+ AssignmentAction Action, bool Elidable) {
if (!getLangOptions().CPlusPlus) {
// In C, argument passing is the same as performing an assignment.
QualType FromType = From->getType();
@@ -2092,7 +2139,7 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
ConvTy = Compatible;
return DiagnoseAssignmentResult(ConvTy, From->getLocStart(), ToType,
- FromType, From, Flavor);
+ FromType, From, Action);
}
if (ToType->isReferenceType())
@@ -2102,13 +2149,13 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
/*AllowExplicit=*/false,
/*ForceRValue=*/false);
- if (!PerformImplicitConversion(From, ToType, Flavor,
+ if (!PerformImplicitConversion(From, ToType, Action,
/*AllowExplicit=*/false, Elidable))
return false;
if (!DiagnoseMultipleUserDefinedConversion(From, ToType))
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_convert_incompatible)
- << ToType << From->getType() << Flavor << From->getSourceRange();
+ << ToType << From->getType() << Action << From->getSourceRange();
return true;
}
@@ -2229,7 +2276,7 @@ ImplicitConversionSequence Sema::TryContextuallyConvertToBool(Expr *From) {
/// of the expression From to bool (C++0x [conv]p3).
bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
ImplicitConversionSequence ICS = TryContextuallyConvertToBool(From);
- if (!PerformImplicitConversion(From, Context.BoolTy, ICS, "converting"))
+ if (!PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting))
return false;
if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
@@ -2622,7 +2669,14 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
Args, NumArgs, Specialization, Info)) {
// FIXME: Record what happened with template argument deduction, so
// that we can give the user a beautiful diagnostic.
- (void)Result;
+ (void) Result;
+
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate &Candidate = CandidateSet.back();
+ Candidate.Function = FunctionTemplate->getTemplatedDecl();
+ Candidate.Viable = false;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
return;
}
@@ -4430,6 +4484,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
bool FoundNonTemplateFunction = false;
for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(),
E = Fns.end(); I != E; ++I) {
+ // Look through any using declarations to find the underlying function.
+ NamedDecl *Fn = (*I)->getUnderlyingDecl();
+
// C++ [over.over]p3:
// Non-member functions and static member functions match
// targets of type "pointer-to-function" or "reference-to-function."
@@ -4438,7 +4495,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// Note that according to DR 247, the containing class does not matter.
if (FunctionTemplateDecl *FunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(*I)) {
+ = dyn_cast<FunctionTemplateDecl>(Fn)) {
if (CXXMethodDecl *Method
= dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
// Skip non-static function templates when converting to pointer, and
@@ -4475,7 +4532,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
continue;
}
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I)) {
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
// Skip non-static functions when converting to pointer, and static
// when converting to member pointer.
if (Method->isStatic() == IsMember)
@@ -4487,7 +4544,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
} else if (IsMember)
continue;
- if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*I)) {
+ if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
QualType ResultTy;
if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
IsNoReturnConversion(Context, FunDecl->getType(), FunctionType,
@@ -4558,6 +4615,93 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
return 0;
}
+/// \brief Given an expression that refers to an overloaded function, try to
+/// resolve that overloaded function expression down to a single function.
+///
+/// This routine can only resolve template-ids that refer to a single function
+/// template, where that template-id refers to a single template whose template
+/// arguments are either provided by the template-id or have defaults,
+/// as described in C++0x [temp.arg.explicit]p3.
+FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
+ // C++ [over.over]p1:
+ // [...] [Note: any redundant set of parentheses surrounding the
+ // overloaded function name is ignored (5.1). ]
+ Expr *OvlExpr = From->IgnoreParens();
+
+ // C++ [over.over]p1:
+ // [...] The overloaded function name can be preceded by the &
+ // operator.
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(OvlExpr)) {
+ if (UnOp->getOpcode() == UnaryOperator::AddrOf)
+ OvlExpr = UnOp->getSubExpr()->IgnoreParens();
+ }
+
+ bool HasExplicitTemplateArgs = false;
+ TemplateArgumentListInfo ExplicitTemplateArgs;
+
+ llvm::SmallVector<NamedDecl*,8> Fns;
+
+ // Look into the overloaded expression.
+ if (UnresolvedLookupExpr *UL
+ = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
+ Fns.append(UL->decls_begin(), UL->decls_end());
+ if (UL->hasExplicitTemplateArgs()) {
+ HasExplicitTemplateArgs = true;
+ UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+ }
+ } else if (UnresolvedMemberExpr *ME
+ = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) {
+ Fns.append(ME->decls_begin(), ME->decls_end());
+ if (ME->hasExplicitTemplateArgs()) {
+ HasExplicitTemplateArgs = true;
+ ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+ }
+ }
+
+ // If we didn't actually find any template-ids, we're done.
+ if (Fns.empty() || !HasExplicitTemplateArgs)
+ return 0;
+
+ // Look through all of the overloaded functions, searching for one
+ // whose type matches exactly.
+ FunctionDecl *Matched = 0;
+ for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(),
+ E = Fns.end(); I != E; ++I) {
+ // C++0x [temp.arg.explicit]p3:
+ // [...] In contexts where deduction is done and fails, or in contexts
+ // where deduction is not done, if a template argument list is
+ // specified and it, along with any default template arguments,
+ // identifies a single function template specialization, then the
+ // template-id is an lvalue for the function template specialization.
+ FunctionTemplateDecl *FunctionTemplate = cast<FunctionTemplateDecl>(*I);
+
+ // C++ [over.over]p2:
+ // If the name is a function template, template argument deduction is
+ // done (14.8.2.2), and if the argument deduction succeeds, the
+ // resulting template argument list is used to generate a single
+ // function template specialization, which is added to the set of
+ // overloaded functions considered.
+ // FIXME: We don't really want to build the specialization here, do we?
+ FunctionDecl *Specialization = 0;
+ TemplateDeductionInfo Info(Context);
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
+ Specialization, Info)) {
+ // FIXME: make a note of the failed deduction for diagnostics.
+ (void)Result;
+ continue;
+ }
+
+ // Multiple matches; we can't resolve to a single declaration.
+ if (Matched)
+ return 0;
+
+ Matched = Specialization;
+ }
+
+ return Matched;
+}
+
/// \brief Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
NamedDecl *Callee,
@@ -4589,10 +4733,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(llvm::SmallVectorImpl<NamedDecl*> &Fns,
- DeclarationName &UnqualifiedName,
- bool ArgumentDependentLookup,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading) {
@@ -4615,28 +4756,99 @@ void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*> &Fns,
//
// then Y is empty.
- if (ArgumentDependentLookup) {
- for (unsigned I = 0; I < Fns.size(); ++I) {
- assert(!Fns[I]->getDeclContext()->isRecord());
- assert(isa<UsingShadowDecl>(Fns[I]) ||
- !Fns[I]->getDeclContext()->isFunctionOrMethod());
- assert(Fns[I]->getUnderlyingDecl()->isFunctionOrFunctionTemplate());
+ if (ULE->requiresADL()) {
+ for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+ E = ULE->decls_end(); I != E; ++I) {
+ assert(!(*I)->getDeclContext()->isRecord());
+ assert(isa<UsingShadowDecl>(*I) ||
+ !(*I)->getDeclContext()->isFunctionOrMethod());
+ assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate());
}
}
#endif
- for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(),
- E = Fns.end(); I != E; ++I)
+ // It would be nice to avoid this copy.
+ TemplateArgumentListInfo TABuffer;
+ const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ if (ULE->hasExplicitTemplateArgs()) {
+ ULE->copyTemplateArgumentsInto(TABuffer);
+ ExplicitTemplateArgs = &TABuffer;
+ }
+
+ for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+ E = ULE->decls_end(); I != E; ++I)
AddOverloadedCallCandidate(*this, *I, ExplicitTemplateArgs,
Args, NumArgs, CandidateSet,
PartialOverloading);
- if (ArgumentDependentLookup)
- AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs,
+ if (ULE->requiresADL())
+ AddArgumentDependentLookupCandidates(ULE->getName(), Args, NumArgs,
ExplicitTemplateArgs,
CandidateSet,
PartialOverloading);
}
+
+static Sema::OwningExprResult Destroy(Sema &SemaRef, Expr *Fn,
+ Expr **Args, unsigned NumArgs) {
+ Fn->Destroy(SemaRef.Context);
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+ Args[Arg]->Destroy(SemaRef.Context);
+ return SemaRef.ExprError();
+}
+
+/// Attempts to recover from a call where no functions were found.
+///
+/// Returns true if new candidates were found.
+static Sema::OwningExprResult
+BuildRecoveryCallExpr(Sema &SemaRef, Expr *Fn,
+ UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc) {
+
+ CXXScopeSpec SS;
+ if (ULE->getQualifier()) {
+ SS.setScopeRep(ULE->getQualifier());
+ SS.setRange(ULE->getQualifierRange());
+ }
+
+ TemplateArgumentListInfo TABuffer;
+ const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ if (ULE->hasExplicitTemplateArgs()) {
+ ULE->copyTemplateArgumentsInto(TABuffer);
+ ExplicitTemplateArgs = &TABuffer;
+ }
+
+ LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
+ Sema::LookupOrdinaryName);
+ if (SemaRef.DiagnoseEmptyLookup(/*Scope=*/0, SS, R))
+ return Destroy(SemaRef, Fn, Args, NumArgs);
+
+ assert(!R.empty() && "lookup results empty despite recovery");
+
+ // Build an implicit member call if appropriate. Just drop the
+ // casts and such from the call, we don't really care.
+ Sema::OwningExprResult NewFn = SemaRef.ExprError();
+ if ((*R.begin())->isCXXClassMember())
+ NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, ExplicitTemplateArgs);
+ else if (ExplicitTemplateArgs)
+ NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs);
+ else
+ NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false);
+
+ if (NewFn.isInvalid())
+ return Destroy(SemaRef, Fn, Args, NumArgs);
+
+ Fn->Destroy(SemaRef.Context);
+
+ // This shouldn't cause an infinite loop because we're giving it
+ // an expression with non-empty lookup results, which should never
+ // end up here.
+ return SemaRef.ActOnCallExpr(/*Scope*/ 0, move(NewFn), LParenLoc,
+ Sema::MultiExprArg(SemaRef, (void**) Args, NumArgs),
+ CommaLocs, RParenLoc);
+}
/// ResolveOverloadedCallFn - Given the call expression that calls Fn
/// (which eventually refers to the declaration Func) and the call
@@ -4645,44 +4857,68 @@ void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*> &Fns,
/// the function declaration produced by overload
/// resolution. Otherwise, emits diagnostics, deletes all of the
/// arguments and Fn, and returns NULL.
-FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn,
- llvm::SmallVectorImpl<NamedDecl*> &Fns,
- DeclarationName UnqualifiedName,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
- SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc,
- bool ArgumentDependentLookup) {
+Sema::OwningExprResult
+Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc) {
+#ifndef NDEBUG
+ if (ULE->requiresADL()) {
+ // To do ADL, we must have found an unqualified name.
+ assert(!ULE->getQualifier() && "qualified name with ADL");
+
+ // We don't perform ADL for implicit declarations of builtins.
+ // Verify that this was correctly set up.
+ FunctionDecl *F;
+ if (ULE->decls_begin() + 1 == ULE->decls_end() &&
+ (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&
+ F->getBuiltinID() && F->isImplicit())
+ assert(0 && "performing ADL for builtin");
+
+ // We don't perform ADL in C.
+ assert(getLangOptions().CPlusPlus && "ADL enabled in C");
+ }
+#endif
+
OverloadCandidateSet CandidateSet;
- // Add the functions denoted by Callee to the set of candidate
- // functions.
- AddOverloadedCallCandidates(Fns, UnqualifiedName, ArgumentDependentLookup,
- ExplicitTemplateArgs, Args, NumArgs,
- CandidateSet);
+ // Add the functions denoted by the callee to the set of candidate
+ // functions, including those from argument-dependent lookup.
+ AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet);
+
+ // If we found nothing, try to recover.
+ // AddRecoveryCallCandidates diagnoses the error itself, so we just
+ // bailout out if it fails.
+ if (CandidateSet.empty())
+ return BuildRecoveryCallExpr(*this, Fn, ULE, LParenLoc, Args, NumArgs,
+ CommaLocs, RParenLoc);
+
OverloadCandidateSet::iterator Best;
switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
- case OR_Success:
- return Best->Function;
+ case OR_Success: {
+ FunctionDecl *FDecl = Best->Function;
+ Fn = FixOverloadedFunctionReference(Fn, FDecl);
+ return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
+ }
case OR_No_Viable_Function:
Diag(Fn->getSourceRange().getBegin(),
diag::err_ovl_no_viable_function_in_call)
- << UnqualifiedName << Fn->getSourceRange();
+ << ULE->getName() << Fn->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
break;
case OR_Ambiguous:
Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call)
- << UnqualifiedName << Fn->getSourceRange();
+ << ULE->getName() << Fn->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
break;
case OR_Deleted:
Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
<< Best->Function->isDeleted()
- << UnqualifiedName
+ << ULE->getName()
<< Fn->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
break;
@@ -4693,7 +4929,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn,
Fn->Destroy(Context);
for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
Args[Arg]->Destroy(Context);
- return 0;
+ return ExprError();
}
static bool IsOverloaded(const Sema::FunctionSet &Functions) {
@@ -4787,10 +5023,16 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
return ExprError();
} else {
// Convert the arguments.
- if (PerformCopyInitialization(Input,
- FnDecl->getParamDecl(0)->getType(),
- "passing"))
+ OwningExprResult InputInit
+ = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ FnDecl->getParamDecl(0)),
+ SourceLocation(),
+ move(input));
+ if (InputInit.isInvalid())
return ExprError();
+
+ input = move(InputInit);
+ Input = (Expr *)input.get();
}
// Determine the result type
@@ -4817,7 +5059,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
// break out so that we will build the appropriate built-in
// operator node.
if (PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0],
- Best->Conversions[0], "passing"))
+ Best->Conversions[0], AA_Passing))
return ExprError();
break;
@@ -4954,17 +5196,40 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
- if (PerformObjectArgumentInitialization(Args[0], Method) ||
- PerformCopyInitialization(Args[1], FnDecl->getParamDecl(0)->getType(),
- "passing"))
+ OwningExprResult Arg1
+ = PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(
+ FnDecl->getParamDecl(0)),
+ SourceLocation(),
+ Owned(Args[1]));
+ if (Arg1.isInvalid())
+ return ExprError();
+
+ if (PerformObjectArgumentInitialization(Args[0], Method))
return ExprError();
+
+ Args[1] = RHS = Arg1.takeAs<Expr>();
} else {
// Convert the arguments.
- if (PerformCopyInitialization(Args[0], FnDecl->getParamDecl(0)->getType(),
- "passing") ||
- PerformCopyInitialization(Args[1], FnDecl->getParamDecl(1)->getType(),
- "passing"))
+ OwningExprResult Arg0
+ = PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(
+ FnDecl->getParamDecl(0)),
+ SourceLocation(),
+ Owned(Args[0]));
+ if (Arg0.isInvalid())
+ return ExprError();
+
+ OwningExprResult Arg1
+ = PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(
+ FnDecl->getParamDecl(1)),
+ SourceLocation(),
+ Owned(Args[1]));
+ if (Arg1.isInvalid())
return ExprError();
+ Args[0] = LHS = Arg0.takeAs<Expr>();
+ Args[1] = RHS = Arg1.takeAs<Expr>();
}
// Determine the result type
@@ -4992,9 +5257,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// break out so that we will build the appropriate built-in
// operator node.
if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
- Best->Conversions[0], "passing") ||
+ Best->Conversions[0], AA_Passing) ||
PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
- Best->Conversions[1], "passing"))
+ Best->Conversions[1], AA_Passing))
return ExprError();
break;
@@ -5106,7 +5371,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
if (PerformObjectArgumentInitialization(Args[0], Method) ||
PerformCopyInitialization(Args[1],
FnDecl->getParamDecl(0)->getType(),
- "passing"))
+ AA_Passing))
return ExprError();
// Determine the result type
@@ -5136,9 +5401,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// break out so that we will build the appropriate built-in
// operator node.
if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
- Best->Conversions[0], "passing") ||
+ Best->Conversions[0], AA_Passing) ||
PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
- Best->Conversions[1], "passing"))
+ Best->Conversions[1], AA_Passing))
return ExprError();
break;
@@ -5522,7 +5787,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// Pass the argument.
QualType ProtoArgType = Proto->getArgType(i);
- IsError |= PerformCopyInitialization(Arg, ProtoArgType, "passing");
+ IsError |= PerformCopyInitialization(Arg, ProtoArgType, AA_Passing);
} else {
OwningExprResult DefArg
= BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index de67a5f..b8928c3 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -95,7 +96,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
// If the callee has attribute pure, const, or warn_unused_result, warn with
// a more specific message to make it clear what is happening.
- if (const FunctionDecl *FD = CE->getDirectCallee()) {
+ if (const Decl *FD = CE->getCalleeDecl()) {
if (FD->getAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result";
return;
@@ -902,7 +903,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
AssignConvertType ConvTy =
CheckSingleAssignmentConstraints(Context.VoidPtrTy, E);
if (DiagnoseAssignmentResult(ConvTy, StarLoc, Context.VoidPtrTy, ETy,
- E, "passing"))
+ E, AA_Passing))
return StmtError();
}
return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
@@ -977,7 +978,6 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
// we have a non-void block with an expression, continue checking
- QualType RetValType = RetValExp->getType();
// 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
@@ -986,7 +986,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
// FIXME: Leaks RetValExp.
- if (PerformCopyInitialization(RetValExp, FnRetType, "returning"))
+ if (PerformCopyInitialization(RetValExp, FnRetType, AA_Returning))
return StmtError();
if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
@@ -1053,7 +1053,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) {
<< RetValExp->getSourceRange();
}
- RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true);
+ RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp);
}
return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
}
@@ -1092,21 +1092,28 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) {
bool Elidable = getLangOptions().CPlusPlus0x ?
IsReturnCopyElidable(Context, FnRetType, RetValExp) :
false;
+ // FIXME: Elidable
+ (void)Elidable;
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
- // FIXME: Leaks RetValExp on error.
- if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable)){
- // We should still clean up our temporaries, even when we're failing!
- RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true);
+ OwningExprResult Res = PerformCopyInitialization(
+ InitializedEntity::InitializeResult(ReturnLoc,
+ FnRetType),
+ SourceLocation(),
+ Owned(RetValExp));
+ if (Res.isInvalid()) {
+ // FIXME: Cleanup temporaries here, anyway?
return StmtError();
}
-
- if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+
+ RetValExp = Res.takeAs<Expr>();
+ if (RetValExp)
+ CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
}
if (RetValExp)
- RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true);
+ RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp);
return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index ac1b1ec..8c6aa6a 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -102,7 +102,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
- LookupResult R(*this, TName, SourceLocation(), LookupOrdinaryName);
+ LookupResult R(*this, TName, Name.getSourceRange().getBegin(),
+ LookupOrdinaryName);
R.suppressDiagnostics();
LookupTemplateName(R, S, SS, ObjectType, EnteringContext);
if (R.empty())
@@ -202,6 +203,29 @@ void Sema::LookupTemplateName(LookupResult &Found,
assert(!Found.isAmbiguous() &&
"Cannot handle template name-lookup ambiguities");
+ if (Found.empty()) {
+ // If we did not find any names, attempt to correct any typos.
+ DeclarationName Name = Found.getLookupName();
+ if (CorrectTypo(Found, S, &SS, LookupCtx)) {
+ FilterAcceptableTemplateNames(Context, Found);
+ if (!Found.empty() && isa<TemplateDecl>(*Found.begin())) {
+ if (LookupCtx)
+ Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
+ << Name << LookupCtx << Found.getLookupName() << SS.getRange()
+ << CodeModificationHint::CreateReplacement(Found.getNameLoc(),
+ Found.getLookupName().getAsString());
+ else
+ Diag(Found.getNameLoc(), diag::err_no_template_suggest)
+ << Name << Found.getLookupName()
+ << CodeModificationHint::CreateReplacement(Found.getNameLoc(),
+ Found.getLookupName().getAsString());
+ } else
+ Found.clear();
+ } else {
+ Found.clear();
+ }
+ }
+
FilterAcceptableTemplateNames(Context, Found);
if (Found.empty())
return;
@@ -691,7 +715,27 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Previous.begin() != Previous.end())
PrevDecl = *Previous.begin();
- if (PrevDecl && TUK == TUK_Friend) {
+ // If there is a previous declaration with the same name, check
+ // whether this is a valid redeclaration.
+ ClassTemplateDecl *PrevClassTemplate
+ = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+
+ // We may have found the injected-class-name of a class template,
+ // class template partial specialization, or class template specialization.
+ // In these cases, grab the template that is being defined or specialized.
+ if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) &&
+ cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
+ PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
+ PrevClassTemplate
+ = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
+ if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
+ PrevClassTemplate
+ = cast<ClassTemplateSpecializationDecl>(PrevDecl)
+ ->getSpecializedTemplate();
+ }
+ }
+
+ if (TUK == TUK_Friend) {
// C++ [namespace.memdef]p3:
// [...] When looking for a prior declaration of a class or a function
// declared as a friend, and when the name of the friend class or
@@ -700,15 +744,16 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
DeclContext *OutermostContext = CurContext;
while (!OutermostContext->isFileContext())
OutermostContext = OutermostContext->getLookupParent();
-
- if (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
- OutermostContext->Encloses(PrevDecl->getDeclContext())) {
+
+ if (PrevDecl &&
+ (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
+ OutermostContext->Encloses(PrevDecl->getDeclContext()))) {
SemanticContext = PrevDecl->getDeclContext();
} else {
// Declarations in outer scopes don't matter. However, the outermost
// context we computed is the semantic context for our new
// declaration.
- PrevDecl = 0;
+ PrevDecl = PrevClassTemplate = 0;
SemanticContext = OutermostContext;
}
@@ -717,30 +762,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// class template to the template in scope, because that would perform
// checking of the template parameter lists that can't be performed
// until the outer context is instantiated.
- PrevDecl = 0;
+ PrevDecl = PrevClassTemplate = 0;
}
} else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
- PrevDecl = 0;
-
- // If there is a previous declaration with the same name, check
- // whether this is a valid redeclaration.
- ClassTemplateDecl *PrevClassTemplate
- = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
-
- // We may have found the injected-class-name of a class template,
- // class template partial specialization, or class template specialization.
- // In these cases, grab the template that is being defined or specialized.
- if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) &&
- cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
- PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
- PrevClassTemplate
- = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
- if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
- PrevClassTemplate
- = cast<ClassTemplateSpecializationDecl>(PrevDecl)
- ->getSpecializedTemplate();
- }
- }
+ PrevDecl = PrevClassTemplate = 0;
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible.
@@ -2188,6 +2213,9 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR;
Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here);
return true;
+ } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
+ SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange();
+ return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
}
return false;
@@ -2484,7 +2512,14 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// Check that we don't overflow the template parameter type.
unsigned AllowedBits = Context.getTypeSize(IntegerType);
- if (Value.getActiveBits() > AllowedBits) {
+ unsigned RequiredBits;
+ if (IntegerType->isUnsignedIntegerType())
+ RequiredBits = Value.getActiveBits();
+ else if (Value.isUnsigned())
+ RequiredBits = Value.getActiveBits() + 1;
+ else
+ RequiredBits = Value.getMinSignedBits();
+ if (RequiredBits > AllowedBits) {
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_too_large)
<< Value.toString(10) << Param->getType()
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index b4754db..21f7996 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -337,58 +337,6 @@ DeduceTemplateArguments(ASTContext &Context,
return Sema::TDK_Success;
}
-/// \brief Returns a completely-unqualified array type, capturing the
-/// qualifiers in Quals.
-///
-/// \param Context the AST context in which the array type was built.
-///
-/// \param T a canonical type that may be an array type.
-///
-/// \param Quals will receive the full set of qualifiers that were
-/// applied to the element type of the array.
-///
-/// \returns if \p T is an array type, the completely unqualified array type
-/// that corresponds to T. Otherwise, returns T.
-static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
- Qualifiers &Quals) {
- assert(T.isCanonical() && "Only operates on canonical types");
- if (!isa<ArrayType>(T)) {
- Quals = T.getLocalQualifiers();
- return T.getLocalUnqualifiedType();
- }
-
- assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
-
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
- QualType Elt = getUnqualifiedArrayType(Context, CAT->getElementType(),
- Quals);
- if (Elt == CAT->getElementType())
- return T;
-
- return Context.getConstantArrayType(Elt, CAT->getSize(),
- CAT->getSizeModifier(), 0);
- }
-
- if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
- QualType Elt = getUnqualifiedArrayType(Context, IAT->getElementType(),
- Quals);
- if (Elt == IAT->getElementType())
- return T;
-
- return Context.getIncompleteArrayType(Elt, IAT->getSizeModifier(), 0);
- }
-
- const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
- QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(),
- Quals);
- if (Elt == DSAT->getElementType())
- return T;
-
- return Context.getDependentSizedArrayType(Elt, DSAT->getSizeExpr()->Retain(),
- DSAT->getSizeModifier(), 0,
- SourceRange());
-}
-
/// \brief Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
@@ -427,9 +375,11 @@ DeduceTemplateArguments(ASTContext &Context,
// referred to by the reference) can be more cv-qualified than the
// transformed A.
if (TDF & TDF_ParamWithReferenceType) {
- Qualifiers Quals = Param.getQualifiers();
- Quals.setCVRQualifiers(Quals.getCVRQualifiers() & Arg.getCVRQualifiers());
- Param = Context.getQualifiedType(Param.getUnqualifiedType(), Quals);
+ Qualifiers Quals;
+ QualType UnqualParam = Context.getUnqualifiedArrayType(Param, Quals);
+ Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
+ Arg.getCVRQualifiersThroughArrayTypes());
+ Param = Context.getQualifiedType(UnqualParam, Quals);
}
// If the parameter type is not dependent, there is nothing to deduce.
@@ -459,7 +409,7 @@ DeduceTemplateArguments(ASTContext &Context,
// FIXME: address spaces, ObjC GC qualifiers
if (isa<ArrayType>(Arg)) {
Qualifiers Quals;
- Arg = getUnqualifiedArrayType(Context, Arg, Quals);
+ Arg = Context.getUnqualifiedArrayType(Arg, Quals);
if (Quals) {
Arg = Context.getQualifiedType(Arg, Quals);
RecanonicalizeArg = true;
@@ -476,7 +426,7 @@ DeduceTemplateArguments(ASTContext &Context,
}
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
-
+ assert(Arg != Context.OverloadTy && "Unresolved overloaded function");
QualType DeducedType = Arg;
DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
if (RecanonicalizeArg)
@@ -1506,15 +1456,39 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
ParamType->getAs<PointerType>()->getPointeeType())))
TDF |= TDF_DerivedClass;
+ // FIXME: C++0x [temp.deduct.call] paragraphs 6-9 deal with function
+ // pointer parameters.
+
+ if (Context.hasSameUnqualifiedType(ArgType, Context.OverloadTy)) {
+ // We know that template argument deduction will fail if the argument is
+ // still an overloaded function. Check whether we can resolve this
+ // argument as a single function template specialization per
+ // C++ [temp.arg.explicit]p3.
+ FunctionDecl *ExplicitSpec
+ = ResolveSingleFunctionTemplateSpecialization(Args[I]);
+ Expr *ResolvedArg = 0;
+ if (ExplicitSpec)
+ ResolvedArg = FixOverloadedFunctionReference(Args[I], ExplicitSpec);
+ if (!ExplicitSpec || !ResolvedArg) {
+ // Template argument deduction fails if we can't resolve the overloaded
+ // function.
+ return TDK_FailedOverloadResolution;
+ }
+
+ // Get the type of the resolved argument.
+ ArgType = ResolvedArg->getType();
+ if (ArgType->isPointerType() || ArgType->isMemberPointerType())
+ TDF |= TDF_IgnoreQualifiers;
+
+ ResolvedArg->Destroy(Context);
+ }
+
if (TemplateDeductionResult Result
= ::DeduceTemplateArguments(Context, TemplateParams,
ParamType, ArgType, Info, Deduced,
TDF))
return Result;
- // FIXME: C++0x [temp.deduct.call] paragraphs 6-9 deal with function
- // pointer parameters.
-
// FIXME: we need to check that the deduced A is the same as A,
// modulo the various allowed differences.
}
@@ -1524,24 +1498,19 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
}
/// \brief Deduce template arguments when taking the address of a function
-/// template (C++ [temp.deduct.funcaddr]) or matching a
+/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
+/// a template.
///
/// \param FunctionTemplate the function template for which we are performing
/// template argument deduction.
///
-/// \param HasExplicitTemplateArgs whether any template arguments were
-/// explicitly specified.
-///
-/// \param ExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
-/// the explicitly-specified template arguments.
-///
-/// \param NumExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
-/// the number of explicitly-specified template arguments in
-/// @p ExplicitTemplateArguments. This value may be zero.
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
///
/// \param ArgFunctionType the function type that will be used as the
/// "argument" type (A) when performing template argument deduction from the
-/// function template's function type.
+/// function template's function type. This type may be NULL, if there is no
+/// argument type to compare against, in C++0x [temp.arg.explicit]p3.
///
/// \param Specialization if template argument deduction was successful,
/// this will be set to the function template specialization produced by
@@ -1578,14 +1547,16 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// Trap any errors that might occur.
SFINAETrap Trap(*this);
- // Deduce template arguments from the function type.
- Deduced.resize(TemplateParams->size());
- if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context, TemplateParams,
- FunctionType, ArgFunctionType, Info,
- Deduced, 0))
- return Result;
-
+ if (!ArgFunctionType.isNull()) {
+ // Deduce template arguments from the function type.
+ Deduced.resize(TemplateParams->size());
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(Context, TemplateParams,
+ FunctionType, ArgFunctionType, Info,
+ Deduced, 0))
+ return Result;
+ }
+
return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
Specialization, Info);
}
@@ -1694,6 +1665,32 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
return Result;
}
+/// \brief Deduce template arguments for a function template when there is
+/// nothing to deduce against (C++0x [temp.arg.explicit]p3).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
+ QualType(), Specialization, Info);
+}
+
/// \brief Stores the result of comparing the qualifiers of two types.
enum DeductionQualifierComparison {
NeitherMoreQualified = 0,
@@ -2354,7 +2351,6 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
// None of these types have any template parameters in them.
case Type::Builtin:
- case Type::FixedWidthInt:
case Type::VariableArray:
case Type::FunctionNoProto:
case Type::Record:
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index dddb93c8..d974f89 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -554,7 +554,6 @@ namespace {
Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E);
Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E);
-
Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
/// \brief Transforms a template type parameter type by performing
@@ -785,7 +784,9 @@ Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
getDescribedFunctionTemplate() &&
"Default arg expressions are never formed in dependent cases.");
- return SemaRef.Owned(E->Retain());
+ return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(),
+ cast<FunctionDecl>(E->getParam()->getDeclContext()),
+ E->getParam());
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8d74bd7..e909c4f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -145,6 +145,11 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
if (Invalid)
Typedef->setInvalidDecl();
+ if (TypedefDecl *Prev = D->getPreviousDeclaration()) {
+ NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(Prev, TemplateArgs);
+ Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
+ }
+
Owner->addDecl(Typedef);
return Typedef;
@@ -396,7 +401,16 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
// FIXME: We have a problem here, because the nested call to Visit(ND)
// will inject the thing that the friend references into the current
// owner, which is wrong.
- Decl *NewND = Visit(ND);
+ Decl *NewND;
+
+ // Hack to make this work almost well pending a rewrite.
+ if (ND->getDeclContext()->isRecord())
+ NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs);
+ else if (D->wasSpecialization()) {
+ // Totally egregious hack to work around PR5866
+ return 0;
+ } else
+ NewND = Visit(ND);
if (!NewND) return 0;
FU = cast<NamedDecl>(NewND);
@@ -645,6 +659,12 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
CXXRecordDecl *PrevDecl = 0;
if (D->isInjectedClassName())
PrevDecl = cast<CXXRecordDecl>(Owner);
+ else if (D->getPreviousDeclaration()) {
+ NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getPreviousDeclaration(),
+ TemplateArgs);
+ if (!Prev) return 0;
+ PrevDecl = cast<CXXRecordDecl>(Prev);
+ }
CXXRecordDecl *Record
= CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
@@ -675,7 +695,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
/// 1) instantiating function templates
/// 2) substituting friend declarations
/// FIXME: preserve function definitions in case #2
- Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
+Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams) {
// Check whether there is already a function template specialization for
// this declaration.
@@ -1149,6 +1169,8 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
if (NewUD->isInvalidDecl())
return NewUD;
+ bool isFunctionScope = Owner->isFunctionOrMethod();
+
// Process the shadow decls.
for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
I != E; ++I) {
@@ -1164,6 +1186,9 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
UsingShadowDecl *InstShadow
= SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
+
+ if (isFunctionScope)
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow);
}
return NewUD;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 37f19f2..ed30229 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -308,7 +308,11 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){
Expr *E = static_cast<Expr *>(DS.getTypeRep());
assert(E && "Didn't get an expression for typeof?");
// TypeQuals handled by caller.
- Result = Context.getTypeOfExprType(E);
+ Result = TheSema.BuildTypeofExprType(E);
+ if (Result.isNull()) {
+ Result = Context.IntTy;
+ TheDeclarator.setInvalidType(true);
+ }
break;
}
case DeclSpec::TST_decltype: {
@@ -1826,14 +1830,41 @@ QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) {
}
QualType Sema::BuildTypeofExprType(Expr *E) {
+ if (E->getType() == Context.OverloadTy) {
+ // C++ [temp.arg.explicit]p3 allows us to resolve a template-id to a
+ // function template specialization wherever deduction cannot occur.
+ if (FunctionDecl *Specialization
+ = ResolveSingleFunctionTemplateSpecialization(E)) {
+ E = FixOverloadedFunctionReference(E, Specialization);
+ if (!E)
+ return QualType();
+ } else {
+ Diag(E->getLocStart(),
+ diag::err_cannot_determine_declared_type_of_overloaded_function)
+ << false << E->getSourceRange();
+ return QualType();
+ }
+ }
+
return Context.getTypeOfExprType(E);
}
QualType Sema::BuildDecltypeType(Expr *E) {
if (E->getType() == Context.OverloadTy) {
- Diag(E->getLocStart(),
- diag::err_cannot_determine_declared_type_of_overloaded_function);
- return QualType();
+ // C++ [temp.arg.explicit]p3 allows us to resolve a template-id to a
+ // function template specialization wherever deduction cannot occur.
+ if (FunctionDecl *Specialization
+ = ResolveSingleFunctionTemplateSpecialization(E)) {
+ E = FixOverloadedFunctionReference(E, Specialization);
+ if (!E)
+ return QualType();
+ } else {
+ Diag(E->getLocStart(),
+ diag::err_cannot_determine_declared_type_of_overloaded_function)
+ << true << E->getSourceRange();
+ return QualType();
+ }
}
+
return Context.getDecltypeType(E);
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index fd19987..208c885 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -956,8 +956,12 @@ public:
// We have a reference to an unnamed field.
assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
+ Expr *BaseExpr = Base.takeAs<Expr>();
+ if (getSema().PerformObjectMemberConversion(BaseExpr, Member))
+ return getSema().ExprError();
+
MemberExpr *ME =
- new (getSema().Context) MemberExpr(Base.takeAs<Expr>(), isArrow,
+ new (getSema().Context) MemberExpr(BaseExpr, isArrow,
Member, MemberLoc,
cast<FieldDecl>(Member)->getType());
return getSema().Owned(ME);
@@ -1358,8 +1362,10 @@ public:
/// By default, builds a new default-argument expression, which does not
/// require any semantic analysis. Subclasses may override this routine to
/// provide different behavior.
- OwningExprResult RebuildCXXDefaultArgExpr(ParmVarDecl *Param) {
- return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Param));
+ OwningExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc,
+ ParmVarDecl *Param) {
+ return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc,
+ Param));
}
/// \brief Build a new C++ zero-initialization expression.
@@ -1655,7 +1661,7 @@ Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
if (E.isInvalid())
return getSema().StmtError();
- return getSema().ActOnExprStmt(getSema().FullExpr(E));
+ return getSema().ActOnExprStmt(getSema().MakeFullExpr(E));
}
}
@@ -2128,13 +2134,6 @@ QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
}
template<typename Derived>
-QualType
-TreeTransform<Derived>::TransformFixedWidthIntType(TypeLocBuilder &TLB,
- FixedWidthIntTypeLoc T) {
- return TransformTypeSpecType(TLB, T);
-}
-
-template<typename Derived>
QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
ComplexTypeLoc T) {
// FIXME: recurse?
@@ -3067,7 +3066,7 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
return SemaRef.StmtError();
}
- Sema::FullExprArg FullCond(getSema().FullExpr(Cond));
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
// Transform the "then" branch.
OwningStmtResult Then = getDerived().TransformStmt(S->getThen());
@@ -3110,7 +3109,7 @@ TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
return SemaRef.StmtError();
}
- Sema::FullExprArg FullCond(getSema().FullExpr(Cond));
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
// Rebuild the switch statement.
OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(FullCond,
@@ -3147,7 +3146,7 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
return SemaRef.StmtError();
}
- Sema::FullExprArg FullCond(getSema().FullExpr(Cond));
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
// Transform the body
OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
@@ -3229,9 +3228,9 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
return SemaRef.Owned(S->Retain());
return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),
- move(Init), getSema().FullExpr(Cond),
+ move(Init), getSema().MakeFullExpr(Cond),
ConditionVar,
- getSema().FullExpr(Inc),
+ getSema().MakeFullExpr(Inc),
S->getRParenLoc(), move(Body));
}
@@ -3688,8 +3687,13 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
Base.get() == E->getBase() &&
Qualifier == E->getQualifier() &&
Member == E->getMemberDecl() &&
- !E->hasExplicitTemplateArgumentList())
+ !E->hasExplicitTemplateArgumentList()) {
+
+ // Mark it referenced in the new context regardless.
+ // FIXME: this is a bit instantiation-specific.
+ SemaRef.MarkDeclarationReferenced(E->getMemberLoc(), Member);
return SemaRef.Owned(E->Retain());
+ }
TemplateArgumentListInfo TransArgs;
if (E->hasExplicitTemplateArgumentList()) {
@@ -4411,7 +4415,7 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
Param == E->getParam())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildCXXDefaultArgExpr(Param);
+ return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param);
}
template<typename Derived>
@@ -4476,6 +4480,31 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
!ArgumentChanged)
return SemaRef.Owned(E->Retain());
+ if (!ArraySize.get()) {
+ // If no array size was specified, but the new expression was
+ // instantiated with an array type (e.g., "new T" where T is
+ // instantiated with "int[4]"), extract the outer bound from the
+ // array type as our array size. We do this with constant and
+ // dependently-sized array types.
+ const ArrayType *ArrayT = SemaRef.Context.getAsArrayType(AllocType);
+ if (!ArrayT) {
+ // Do nothing
+ } else if (const ConstantArrayType *ConsArrayT
+ = dyn_cast<ConstantArrayType>(ArrayT)) {
+ ArraySize
+ = SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
+ ConsArrayT->getSize(),
+ SemaRef.Context.getSizeType(),
+ /*FIXME:*/E->getLocStart()));
+ AllocType = ConsArrayT->getElementType();
+ } else if (const DependentSizedArrayType *DepArrayT
+ = dyn_cast<DependentSizedArrayType>(ArrayT)) {
+ if (DepArrayT->getSizeExpr()) {
+ ArraySize = SemaRef.Owned(DepArrayT->getSizeExpr()->Retain());
+ AllocType = DepArrayT->getElementType();
+ }
+ }
+ }
return getDerived().RebuildCXXNewExpr(E->getLocStart(),
E->isGlobalNew(),
/*FIXME:*/E->getLocStart(),
@@ -4725,38 +4754,24 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
/// \brief Transform a C++ temporary-binding expression.
///
-/// The transformation of a temporary-binding expression always attempts to
-/// bind a new temporary variable to its subexpression, even if the
-/// subexpression itself did not change, because the temporary variable itself
-/// must be unique.
+/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just
+/// transform the subexpression and return that.
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
- if (SubExpr.isInvalid())
- return SemaRef.ExprError();
-
- return SemaRef.MaybeBindToTemporary(SubExpr.takeAs<Expr>());
+ return getDerived().TransformExpr(E->getSubExpr());
}
/// \brief Transform a C++ expression that contains temporaries that should
/// be destroyed after the expression is evaluated.
///
-/// The transformation of a full expression always attempts to build a new
-/// CXXExprWithTemporaries expression, even if the
-/// subexpression itself did not change, because it will need to capture the
-/// the new temporary variables introduced in the subexpression.
+/// Since CXXExprWithTemporaries nodes are implicitly generated, we
+/// just transform the subexpression and return that.
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXExprWithTemporaries(
- CXXExprWithTemporaries *E) {
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
- if (SubExpr.isInvalid())
- return SemaRef.ExprError();
-
- return SemaRef.Owned(
- SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>(),
- E->shouldDestroyTemporaries()));
+ CXXExprWithTemporaries *E) {
+ return getDerived().TransformExpr(E->getSubExpr());
}
template<typename Derived>
@@ -5233,9 +5248,6 @@ TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
break;
}
- if (SizeType.isNull())
- SizeType = SemaRef.Context.getFixedWidthIntType(Size->getBitWidth(), false);
-
IntegerLiteral ArraySize(*Size, SizeType, /*FIXME*/BracketsRange.getBegin());
return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize,
IndexTypeQuals, BracketsRange,
OpenPOWER on IntegriCloud