summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp768
1 files changed, 451 insertions, 317 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 2dfb954..c4ab03f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -16,10 +16,13 @@
#include "Lookup.h"
#include "AnalysisBasedWarnings.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -80,6 +83,9 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
const SentinelAttr *attr = D->getAttr<SentinelAttr>();
if (!attr)
return;
+
+ // FIXME: In C++0x, if any of the arguments are parameter pack
+ // expansions, we can't check for the sentinel now.
int sentinelPos = attr->getSentinel();
int nullPos = attr->getNullPos();
@@ -155,6 +161,8 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
}
Expr *sentinelExpr = Args[sentinel];
if (sentinelExpr && (!isa<GNUNullExpr>(sentinelExpr) &&
+ !sentinelExpr->isTypeDependent() &&
+ !sentinelExpr->isValueDependent() &&
(!sentinelExpr->getType()->isPointerType() ||
!sentinelExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)))) {
@@ -454,7 +462,10 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
}
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
+ if (isa<NonTypeTemplateParmDecl>(VD)) {
+ // Non-type template parameters can be referenced anywhere they are
+ // visible.
+ } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
if (const FunctionDecl *FD = MD->getParent()->isLocalClass()) {
if (VD->hasLocalStorage() && VD->getDeclContext() != CurContext) {
Diag(Loc, diag::err_reference_to_local_var_in_enclosing_function)
@@ -769,24 +780,6 @@ static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
return true;
}
-/// Determines if this is an instance member of a class.
-static bool IsInstanceMember(NamedDecl *D) {
- assert(D->isCXXClassMember() &&
- "checking whether non-member is instance member");
-
- if (isa<FieldDecl>(D)) return true;
-
- if (isa<CXXMethodDecl>(D))
- return !cast<CXXMethodDecl>(D)->isStatic();
-
- if (isa<FunctionTemplateDecl>(D)) {
- D = cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
- return !cast<CXXMethodDecl>(D)->isStatic();
- }
-
- return false;
-}
-
enum IMAKind {
/// The reference is definitely not an instance member access.
IMA_Static,
@@ -846,8 +839,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
bool hasNonInstance = false;
llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- NamedDecl *D = (*I)->getUnderlyingDecl();
- if (IsInstanceMember(D)) {
+ NamedDecl *D = *I;
+ if (D->isCXXInstanceMember()) {
CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
// If this is a member of an anonymous record, move out to the
@@ -913,7 +906,7 @@ static void DiagnoseInstanceReference(Sema &SemaRef,
/// Diagnose an empty lookup.
///
/// \return false if new lookup candidates were found
-bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS,
+bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS,
LookupResult &R) {
DeclarationName Name = R.getLookupName();
@@ -964,43 +957,55 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS,
}
// 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()
- << FixItHint::CreateReplacement(R.getNameLoc(),
- R.getLookupName().getAsString());
- else
- Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << R.getLookupName()
- << SS.getRange()
- << FixItHint::CreateReplacement(R.getNameLoc(),
- R.getLookupName().getAsString());
- if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
- Diag(ND->getLocation(), diag::note_previous_decl)
- << ND->getDeclName();
-
- // Tell the callee to try to recover.
- return false;
- }
+ DeclarationName Corrected;
+ if (S && (Corrected = CorrectTypo(R, S, &SS))) {
+ if (!R.empty()) {
+ if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) {
+ if (SS.isEmpty())
+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName()
+ << FixItHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+ else
+ Diag(R.getNameLoc(), diag::err_no_member_suggest)
+ << Name << computeDeclContext(SS, false) << R.getLookupName()
+ << SS.getRange()
+ << FixItHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+ if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(), diag::note_previous_decl)
+ << ND->getDeclName();
+
+ // 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();
- 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.
+ // Don't try to recover; it won't work.
+ return true;
+ }
+ } else {
+ // FIXME: We found a keyword. Suggest it, but don't provide a fix-it
+ // because we aren't able to recover.
if (SS.isEmpty())
- Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName();
+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << Corrected;
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.
+ << Name << computeDeclContext(SS, false) << Corrected
+ << SS.getRange();
return true;
}
-
R.clear();
}
@@ -1019,7 +1024,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS,
}
Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
- const CXXScopeSpec &SS,
+ CXXScopeSpec &SS,
UnqualifiedId &Id,
bool HasTrailingLParen,
bool isAddressOfOperand) {
@@ -1064,6 +1069,15 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
if (TemplateArgs) {
// Just re-use the lookup done by isTemplateName.
DecomposeTemplateName(R, Id);
+
+ // Re-derive the naming class.
+ if (SS.isSet()) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (const Type *Ty = Qualifier->getAsType())
+ if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl())
+ R.setNamingClass(NamingClass);
+ }
} else {
bool IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl());
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
@@ -1123,16 +1137,15 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
// Warn about constructs like:
// if (void *X = foo()) { ... } else { X }.
// In the else block, the pointer is always false.
-
if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
Scope *CheckS = S;
while (CheckS && CheckS->getControlParent()) {
- if (CheckS->isWithinElse() &&
+ if ((CheckS->getFlags() & Scope::ElseScope) &&
CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
ExprError(Diag(NameLoc, diag::warn_value_always_zero)
<< Var->getDeclName()
- << (Var->getType()->isPointerType()? 2 :
- Var->getType()->isBooleanType()? 1 : 0));
+ << (Var->getType()->isPointerType() ? 2 :
+ Var->getType()->isBooleanType() ? 1 : 0));
break;
}
@@ -1218,15 +1231,16 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
/// There's a large number of things which don't need to be done along
/// this path.
Sema::OwningExprResult
-Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
+Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
DeclarationName Name,
SourceLocation NameLoc) {
DeclContext *DC;
- if (!(DC = computeDeclContext(SS, false)) ||
- DC->isDependentContext() ||
- RequireCompleteDeclContext(SS))
+ if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext())
return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0);
+ if (RequireCompleteDeclContext(SS, DC))
+ return ExprError();
+
LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
LookupQualifiedName(R, DC);
@@ -1251,9 +1265,9 @@ Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
/// Returns a null sentinel to indicate trivial success.
Sema::OwningExprResult
Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
- IdentifierInfo *II,
- bool AllowBuiltinCreation) {
+ IdentifierInfo *II, bool AllowBuiltinCreation) {
SourceLocation Loc = Lookup.getNameLoc();
+ ObjCMethodDecl *CurMethod = getCurMethodDecl();
// There are two cases to handle here. 1) scoped lookup could have failed,
// in which case we should look for an ivar. 2) scoped lookup could have
@@ -1264,7 +1278,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
// If we're in a class method, we don't normally want to look for
// ivars. But if we don't find anything else, and there's an
// ivar, that's an error.
- bool IsClassMethod = getCurMethodDecl()->isClassMethod();
+ bool IsClassMethod = CurMethod->isClassMethod();
bool LookForIvars;
if (Lookup.empty())
@@ -1276,7 +1290,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
ObjCInterfaceDecl *IFace = 0;
if (LookForIvars) {
- IFace = getCurMethodDecl()->getClassInterface();
+ IFace = CurMethod->getClassInterface();
ObjCInterfaceDecl *ClassDeclared;
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
// Diagnose using an ivar in a class method.
@@ -1311,9 +1325,9 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
ObjCIvarRefExpr(IV, IV->getType(), Loc,
SelfExpr.takeAs<Expr>(), true, true));
}
- } else if (getCurMethodDecl()->isInstanceMethod()) {
+ } else if (CurMethod->isInstanceMethod()) {
// We should warn if a local variable hides an ivar.
- ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
+ ObjCInterfaceDecl *IFace = CurMethod->getClassInterface();
ObjCInterfaceDecl *ClassDeclared;
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
if (IV->getAccessControl() != ObjCIvarDecl::Private ||
@@ -1322,17 +1336,6 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
}
}
- // Needed to implement property "super.method" notation.
- if (Lookup.empty() && II->isStr("super")) {
- QualType T;
-
- if (getCurMethodDecl()->isInstanceMethod())
- T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
- getCurMethodDecl()->getClassInterface()));
- else
- T = Context.getObjCClassType();
- return Owned(new (Context) ObjCSuperExpr(Loc, T));
- }
if (Lookup.empty() && II && AllowBuiltinCreation) {
// FIXME. Consolidate this with similar code in LookupName.
if (unsigned BuiltinID = II->getBuiltinID()) {
@@ -1449,14 +1452,15 @@ Sema::PerformObjectMemberConversion(Expr *&From,
// type of the object type, in which case we just ignore it.
// Otherwise build the appropriate casts.
if (IsDerivedFrom(FromRecordType, QRecordType)) {
+ CXXBaseSpecifierArray BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
- FromLoc, FromRange))
+ FromLoc, FromRange, &BasePath))
return true;
if (PointerConversions)
QType = Context.getPointerType(QType);
ImpCastExprToType(From, QType, CastExpr::CK_UncheckedDerivedToBase,
- /*isLvalue*/ !PointerConversions);
+ /*isLvalue=*/!PointerConversions, BasePath);
FromType = QType;
FromRecordType = QRecordType;
@@ -1484,15 +1488,16 @@ Sema::PerformObjectMemberConversion(Expr *&From,
// conversion is non-trivial.
if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
assert(IsDerivedFrom(FromRecordType, URecordType));
+ CXXBaseSpecifierArray BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
- FromLoc, FromRange))
+ FromLoc, FromRange, &BasePath))
return true;
-
+
QualType UType = URecordType;
if (PointerConversions)
UType = Context.getPointerType(UType);
ImpCastExprToType(From, UType, CastExpr::CK_UncheckedDerivedToBase,
- /*isLvalue*/ !PointerConversions);
+ /*isLvalue=*/!PointerConversions, BasePath);
FromType = UType;
FromRecordType = URecordType;
}
@@ -1502,23 +1507,22 @@ Sema::PerformObjectMemberConversion(Expr *&From,
IgnoreAccess = true;
}
- if (CheckDerivedToBaseConversion(FromRecordType,
- DestRecordType,
- FromLoc,
- FromRange,
+ CXXBaseSpecifierArray BasePath;
+ if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
+ FromLoc, FromRange, &BasePath,
IgnoreAccess))
return true;
ImpCastExprToType(From, DestType, CastExpr::CK_UncheckedDerivedToBase,
- /*isLvalue=*/ !PointerConversions);
+ /*isLvalue=*/!PointerConversions, BasePath);
return false;
}
/// \brief Build a MemberExpr AST node.
static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
const CXXScopeSpec &SS, ValueDecl *Member,
- NamedDecl *FoundDecl, SourceLocation Loc,
- QualType Ty,
+ DeclAccessPair FoundDecl,
+ SourceLocation Loc, QualType Ty,
const TemplateArgumentListInfo *TemplateArgs = 0) {
NestedNameSpecifier *Qualifier = 0;
SourceRange QualifierRange;
@@ -2484,7 +2488,8 @@ Sema::ActOnDependentMemberExpr(ExprArg Base, QualType BaseType,
}
}
- assert(BaseType->isDependentType() || Name.isDependentName());
+ assert(BaseType->isDependentType() || Name.isDependentName() ||
+ isDependentScopeSpecifier(SS));
// Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
// must have pointer type, and the accessed type is the pointee.
@@ -2510,11 +2515,8 @@ static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
if (!BaseExpr)
return DiagnoseInstanceReference(SemaRef, SS, R);
- // FIXME: this is an exceedingly lame diagnostic for some of the more
- // complicated cases here.
- DeclContext *DC = R.getRepresentativeDecl()->getDeclContext();
- SemaRef.Diag(R.getNameLoc(), diag::err_not_direct_base_or_virtual)
- << SS.getRange() << DC << BaseType;
+ SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_of_unrelated)
+ << SS.getRange() << R.getRepresentativeDecl() << BaseType;
}
// Check whether the declarations we found through a nested-name
@@ -2545,7 +2547,7 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
// If this is an implicit member reference and we find a
// non-instance member, it's not an error.
- if (!BaseExpr && !IsInstanceMember((*I)->getUnderlyingDecl()))
+ if (!BaseExpr && !(*I)->isCXXInstanceMember())
return false;
// Note that we use the DC of the decl, not the underlying decl.
@@ -2567,7 +2569,7 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
static bool
LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
SourceRange BaseRange, const RecordType *RTy,
- SourceLocation OpLoc, const CXXScopeSpec &SS) {
+ SourceLocation OpLoc, CXXScopeSpec &SS) {
RecordDecl *RDecl = RTy->getDecl();
if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
@@ -2580,7 +2582,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
// nested-name-specifier.
DC = SemaRef.computeDeclContext(SS, false);
- if (SemaRef.RequireCompleteDeclContext(SS)) {
+ if (SemaRef.RequireCompleteDeclContext(SS, DC)) {
SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
<< SS.getRange() << DC;
return true;
@@ -2604,7 +2606,8 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
// 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) &&
+ if (SemaRef.CorrectTypo(R, 0, &SS, DC, false, Sema::CTC_MemberLookup) &&
+ !R.empty() &&
(isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) {
SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
<< Name << DC << R.getLookupName() << SS.getRange()
@@ -2624,7 +2627,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
Sema::OwningExprResult
Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType,
SourceLocation OpLoc, bool IsArrow,
- const CXXScopeSpec &SS,
+ CXXScopeSpec &SS,
NamedDecl *FirstQualifierInScope,
DeclarationName Name, SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs) {
@@ -2675,13 +2678,15 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
const CXXScopeSpec &SS,
NamedDecl *FirstQualifierInScope,
LookupResult &R,
- const TemplateArgumentListInfo *TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool SuppressQualifierCheck) {
Expr *BaseExpr = Base.takeAs<Expr>();
QualType BaseType = BaseExprType;
if (IsArrow) {
assert(BaseType->isPointerType());
BaseType = BaseType->getAs<PointerType>()->getPointeeType();
}
+ R.setBaseObjectType(BaseType);
NestedNameSpecifier *Qualifier =
static_cast<NestedNameSpecifier*>(SS.getScopeRep());
@@ -2713,6 +2718,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
if ((SS.isSet() || !BaseExpr ||
(isa<CXXThisExpr>(BaseExpr) &&
cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&
+ !SuppressQualifierCheck &&
CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
return ExprError();
@@ -2742,7 +2748,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
}
assert(R.isSingleResult());
- NamedDecl *FoundDecl = *R.begin();
+ DeclAccessPair FoundDecl = R.begin().getPair();
NamedDecl *MemberDecl = R.getFoundDecl();
// FIXME: diagnose the presence of template arguments now.
@@ -2756,7 +2762,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
// Handle the implicit-member-access case.
if (!BaseExpr) {
// If this is not an instance member, convert to a non-member access.
- if (!IsInstanceMember(MemberDecl))
+ if (!MemberDecl->isCXXInstanceMember())
return BuildDeclarationNameExpr(SS, R.getNameLoc(), MemberDecl);
SourceLocation Loc = R.getNameLoc();
@@ -2833,16 +2839,18 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
Owned(BaseExpr);
+ // We found something that we didn't expect. Complain.
if (isa<TypeDecl>(MemberDecl))
- return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
- << MemberName << int(IsArrow));
+ Diag(MemberLoc,diag::err_typecheck_member_reference_type)
+ << MemberName << BaseType << int(IsArrow);
+ else
+ Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)
+ << MemberName << BaseType << int(IsArrow);
- // We found a declaration kind that we didn't expect. This is a
- // generic error message that tells the user that she can't refer
- // to this member with '.' or '->'.
- return ExprError(Diag(MemberLoc,
- diag::err_typecheck_member_reference_unknown)
- << MemberName << int(IsArrow));
+ Diag(MemberDecl->getLocation(), diag::note_member_declared_here)
+ << MemberName;
+ R.suppressDiagnostics();
+ return ExprError();
}
/// Look up the given member of the given non-type-dependent
@@ -2858,7 +2866,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
Sema::OwningExprResult
Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
bool &IsArrow, SourceLocation OpLoc,
- const CXXScopeSpec &SS,
+ CXXScopeSpec &SS,
DeclPtrTy ObjCImpDecl) {
assert(BaseExpr && "no base expression");
@@ -3060,7 +3068,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// Attempt to correct for typos in ivar names.
LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
LookupMemberName);
- if (CorrectTypo(Res, 0, 0, IDecl) &&
+ if (CorrectTypo(Res, 0, 0, IDecl, false, CTC_MemberLookup) &&
(IV = Res.getAsSingle<ObjCIvarDecl>())) {
Diag(R.getNameLoc(),
diag::err_typecheck_member_reference_ivar_suggest)
@@ -3145,117 +3153,23 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
if (DiagnoseUseOfDecl(OMD, MemberLoc))
return ExprError();
- return Owned(new (Context) ObjCMessageExpr(Context, BaseExpr, Sel,
- OMD->getResultType(),
- OMD, OpLoc, MemberLoc,
- NULL, 0));
+ return Owned(ObjCMessageExpr::Create(Context,
+ OMD->getResultType().getNonReferenceType(),
+ OpLoc, BaseExpr, Sel,
+ OMD, NULL, 0, MemberLoc));
}
}
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
}
+
// Handle Objective-C property access, which is "Obj.property" where Obj is a
// pointer to a (potentially qualified) interface type.
- const ObjCObjectPointerType *OPT;
- if (!IsArrow && (OPT = BaseType->getAsObjCInterfacePointerType())) {
- const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
- ObjCInterfaceDecl *IFace = IFaceT->getDecl();
- IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
-
- // Search for a declared property first.
- if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
- // Check whether we can reference this property.
- if (DiagnoseUseOfDecl(PD, MemberLoc))
- return ExprError();
- QualType ResTy = PD->getType();
- Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
- ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
- if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))
- ResTy = Getter->getResultType();
- return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
- MemberLoc, BaseExpr));
- }
- // Check protocols on qualified interfaces.
- for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
- E = OPT->qual_end(); I != E; ++I)
- if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
- // Check whether we can reference this property.
- if (DiagnoseUseOfDecl(PD, MemberLoc))
- return ExprError();
-
- return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
- MemberLoc, BaseExpr));
- }
- // If that failed, look for an "implicit" property by seeing if the nullary
- // selector is implemented.
-
- // FIXME: The logic for looking up nullary and unary selectors should be
- // shared with the code in ActOnInstanceMessage.
-
- Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
- ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
-
- // If this reference is in an @implementation, check for 'private' methods.
- if (!Getter)
- Getter = IFace->lookupPrivateInstanceMethod(Sel);
-
- // Look through local category implementations associated with the class.
- if (!Getter)
- Getter = IFace->getCategoryInstanceMethod(Sel);
- if (Getter) {
- // Check if we can reference this property.
- if (DiagnoseUseOfDecl(Getter, MemberLoc))
- return ExprError();
- }
- // If we found a getter then this may be a valid dot-reference, we
- // will look for the matching setter, in case it is needed.
- Selector SetterSel =
- SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(), Member);
- ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
- if (!Setter) {
- // If this reference is in an @implementation, also check for 'private'
- // methods.
- Setter = IFace->lookupPrivateInstanceMethod(SetterSel);
- }
- // Look through local category implementations associated with the class.
- if (!Setter)
- Setter = IFace->getCategoryInstanceMethod(SetterSel);
-
- if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
- return ExprError();
-
- if (Getter) {
- QualType PType;
- PType = Getter->getResultType();
- return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
- Setter, MemberLoc, BaseExpr));
- }
-
- // Attempt to correct for typos in property names.
- LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
- LookupOrdinaryName);
- if (CorrectTypo(Res, 0, 0, IFace, false, OPT) &&
- Res.getAsSingle<ObjCPropertyDecl>()) {
- Diag(R.getNameLoc(), diag::err_property_not_found_suggest)
- << MemberName << BaseType << Res.getLookupName()
- << FixItHint::CreateReplacement(R.getNameLoc(),
- Res.getLookupName().getAsString());
- ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>();
- Diag(Property->getLocation(), diag::note_previous_decl)
- << Property->getDeclName();
-
- return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl);
- }
- Diag(MemberLoc, diag::err_property_not_found)
- << MemberName << BaseType;
- if (Setter && !Getter)
- Diag(Setter->getLocation(), diag::note_getter_unavailable)
- << MemberName << BaseExpr->getSourceRange();
- return ExprError();
- }
+ if (!IsArrow)
+ if (const ObjCObjectPointerType *OPT =
+ BaseType->getAsObjCInterfacePointerType())
+ return HandleExprPropertyRefExpr(OPT, BaseExpr, MemberName, MemberLoc);
// Handle the following exceptional case (*Obj).isa.
if (!IsArrow &&
@@ -3296,7 +3210,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
SourceLocation OpLoc,
tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
+ CXXScopeSpec &SS,
UnqualifiedId &Id,
DeclPtrTy ObjCImpDecl,
bool HasTrailingLParen) {
@@ -3323,7 +3237,8 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
Expr *Base = BaseArg.takeAs<Expr>();
OwningExprResult Result(*this);
- if (Base->getType()->isDependentType() || Name.isDependentName()) {
+ if (Base->getType()->isDependentType() || Name.isDependentName() ||
+ isDependentScopeSpecifier(SS)) {
Result = ActOnDependentMemberExpr(ExprArg(*this, Base), Base->getType(),
IsArrow, OpLoc,
SS, FirstQualifierInScope,
@@ -3334,6 +3249,21 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
if (TemplateArgs) {
// Re-use the lookup done for the template name.
DecomposeTemplateName(R, Id);
+
+ // Re-derive the naming class.
+ if (SS.isSet()) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (const Type *Ty = Qualifier->getAsType())
+ if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl())
+ R.setNamingClass(NamingClass);
+ } else {
+ QualType BaseType = Base->getType();
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+ if (CXXRecordDecl *NamingClass = BaseType->getAsCXXRecordDecl())
+ R.setNamingClass(NamingClass);
+ }
} else {
Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
SS, ObjCImpDecl);
@@ -3443,7 +3373,8 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
if (NumArgs < NumArgsInProto) {
if (!FDecl || NumArgs < FDecl->getMinRequiredArguments())
return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
- << Fn->getType()->isBlockPointerType() << Fn->getSourceRange();
+ << Fn->getType()->isBlockPointerType()
+ << NumArgsInProto << NumArgs << Fn->getSourceRange();
Call->setNumArgs(Context, NumArgsInProto);
}
@@ -3453,7 +3384,8 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
if (!Proto->isVariadic()) {
Diag(Args[NumArgsInProto]->getLocStart(),
diag::err_typecheck_call_too_many_args)
- << Fn->getType()->isBlockPointerType() << Fn->getSourceRange()
+ << Fn->getType()->isBlockPointerType()
+ << NumArgsInProto << NumArgs << Fn->getSourceRange()
<< SourceRange(Args[NumArgsInProto]->getLocStart(),
Args[NumArgs-1]->getLocEnd());
// This deletes the extra arguments.
@@ -3613,7 +3545,8 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
// declarations (all methods or method templates) or a single
// method template.
assert((MemE->getNumDecls() > 1) ||
- isa<FunctionTemplateDecl>(*MemE->decls_begin()));
+ isa<FunctionTemplateDecl>(
+ (*MemE->decls_begin())->getUnderlyingDecl()));
(void)MemE;
return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
@@ -3666,7 +3599,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
Expr *NakedFn = Fn->IgnoreParens();
if (isa<UnresolvedLookupExpr>(NakedFn)) {
UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
- return BuildOverloadedCallExpr(Fn, ULE, LParenLoc, Args, NumArgs,
+ return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
CommaLocs, RParenLoc);
}
@@ -3851,8 +3784,8 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
// Semantic analysis for initializers is done by ActOnDeclarator() and
// CheckInitializer() - it requires knowledge of the object being intialized.
- InitListExpr *E = new (Context) InitListExpr(LBraceLoc, InitList, NumInit,
- RBraceLoc);
+ InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitList,
+ NumInit, RBraceLoc);
E->setType(Context.VoidTy); // FIXME: just a place holder for now.
return Owned(E);
}
@@ -3895,11 +3828,11 @@ static CastExpr::CastKind getScalarCastKind(ASTContext &Context,
/// CheckCastTypes - Check type constraints for casting between types.
bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
CastExpr::CastKind& Kind,
- CXXMethodDecl *& ConversionDecl,
+ CXXBaseSpecifierArray &BasePath,
bool FunctionalStyle) {
if (getLangOptions().CPlusPlus)
- return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle,
- ConversionDecl);
+ return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, BasePath,
+ FunctionalStyle);
DefaultFunctionArrayLvalueConversion(castExpr);
@@ -3962,9 +3895,6 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
if (castExpr->getType()->isVectorType())
return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
- if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr))
- return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR;
-
if (isa<ObjCSelectorExpr>(castExpr))
return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
@@ -4062,27 +3992,15 @@ Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
SourceLocation RParenLoc, ExprArg Op) {
Expr *castExpr = static_cast<Expr*>(Op.get());
- CXXMethodDecl *Method = 0;
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+ CXXBaseSpecifierArray BasePath;
if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
- Kind, Method))
+ Kind, BasePath))
return ExprError();
- if (Method) {
- // FIXME: preserve type source info here
- OwningExprResult CastArg = BuildCXXCastArgument(LParenLoc, Ty->getType(),
- Kind, Method, move(Op));
-
- if (CastArg.isInvalid())
- return ExprError();
-
- castExpr = CastArg.takeAs<Expr>();
- } else {
- Op.release();
- }
-
+ Op.release();
return Owned(new (Context) CStyleCastExpr(Ty->getType().getNonReferenceType(),
- Kind, castExpr, Ty,
+ Kind, castExpr, BasePath, Ty,
LParenLoc, RParenLoc));
}
@@ -4126,7 +4044,8 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
// FIXME: This means that pretty-printing the final AST will produce curly
// braces instead of the original commas.
Op.release();
- InitListExpr *E = new (Context) InitListExpr(LParenLoc, &initExprs[0],
+ InitListExpr *E = new (Context) InitListExpr(Context, LParenLoc,
+ &initExprs[0],
initExprs.size(), RParenLoc);
E->setType(Ty);
return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, Owned(E));
@@ -4856,7 +4775,7 @@ static void ConstructTransparentUnion(ASTContext &C, Expr *&E,
QualType UnionType, FieldDecl *Field) {
// Build an initializer list that designates the appropriate member
// of the transparent union.
- InitListExpr *Initializer = new (C) InitListExpr(SourceLocation(),
+ InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(),
&E, 1,
SourceLocation());
Initializer->setType(UnionType);
@@ -5419,11 +5338,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
DiagRuntimeBehavior(Loc,
PDiag(diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(literalStringStripped)
- << literalString->getSourceRange()
- << FixItHint::CreateReplacement(SourceRange(Loc), ", ")
- << FixItHint::CreateInsertion(lex->getLocStart(), "strcmp(")
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(rex->getLocEnd()),
- resultComparison));
+ << literalString->getSourceRange());
}
}
@@ -5480,7 +5395,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
// C++ [expr.eq]p1 uses the same notion for (in)equality
// comparisons of pointers.
bool NonStandardCompositeType = false;
- QualType T = FindCompositePointerType(lex, rex,
+ QualType T = FindCompositePointerType(Loc, lex, rex,
isSFINAEContext()? 0 : &NonStandardCompositeType);
if (T.isNull()) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
@@ -5553,7 +5468,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
// that is the union of the cv-qualification signatures of the operand
// types.
bool NonStandardCompositeType = false;
- QualType T = FindCompositePointerType(lex, rex,
+ QualType T = FindCompositePointerType(Loc, lex, rex,
isSFINAEContext()? 0 : &NonStandardCompositeType);
if (T.isNull()) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
@@ -5944,7 +5859,7 @@ QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) {
/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
- bool isInc) {
+ bool isInc, bool isPrefix) {
if (Op->isTypeDependent())
return Context.DependentTy;
@@ -6007,7 +5922,11 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
// Now make sure the operand is a modifiable lvalue.
if (CheckForModifiableLvalue(Op, OpLoc, *this))
return QualType();
- return ResType;
+ // In C++, a prefix increment is the same type as the operand. Otherwise
+ // (in C or with postfix), the increment is the unqualified type of the
+ // operand.
+ return isPrefix && getLangOptions().CPlusPlus
+ ? ResType : ResType.getUnqualifiedType();
}
/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
@@ -6395,33 +6314,37 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
/// ParenRange in parentheses.
static void SuggestParentheses(Sema &Self, SourceLocation Loc,
const PartialDiagnostic &PD,
- SourceRange ParenRange,
- const PartialDiagnostic &SecondPD,
+ const PartialDiagnostic &FirstNote,
+ SourceRange FirstParenRange,
+ const PartialDiagnostic &SecondNote,
SourceRange SecondParenRange) {
- SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
- if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
- // We can't display the parentheses, so just dig the
- // warning/error and return.
- Self.Diag(Loc, PD);
+ Self.Diag(Loc, PD);
+
+ if (!FirstNote.getDiagID())
+ return;
+
+ SourceLocation EndLoc = Self.PP.getLocForEndOfToken(FirstParenRange.getEnd());
+ if (!FirstParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+ // We can't display the parentheses, so just return.
return;
}
- Self.Diag(Loc, PD)
- << FixItHint::CreateInsertion(ParenRange.getBegin(), "(")
+ Self.Diag(Loc, FirstNote)
+ << FixItHint::CreateInsertion(FirstParenRange.getBegin(), "(")
<< FixItHint::CreateInsertion(EndLoc, ")");
- if (!SecondPD.getDiagID())
+ if (!SecondNote.getDiagID())
return;
EndLoc = Self.PP.getLocForEndOfToken(SecondParenRange.getEnd());
if (!SecondParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
// We can't display the parentheses, so just dig the
// warning/error and return.
- Self.Diag(Loc, SecondPD);
+ Self.Diag(Loc, SecondNote);
return;
}
- Self.Diag(Loc, SecondPD)
+ Self.Diag(Loc, SecondNote)
<< FixItHint::CreateInsertion(SecondParenRange.getBegin(), "(")
<< FixItHint::CreateInsertion(EndLoc, ")");
}
@@ -6455,19 +6378,23 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc,
Self.PDiag(diag::warn_precedence_bitwise_rel)
<< SourceRange(lhs->getLocStart(), OpLoc)
<< BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc),
- lhs->getSourceRange(),
Self.PDiag(diag::note_precedence_bitwise_first)
<< BinOp::getOpcodeStr(Opc),
- SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()));
+ SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()),
+ Self.PDiag(diag::note_precedence_bitwise_silence)
+ << BinOp::getOpcodeStr(lhsopc),
+ lhs->getSourceRange());
else if (BinOp::isComparisonOp(rhsopc))
SuggestParentheses(Self, OpLoc,
Self.PDiag(diag::warn_precedence_bitwise_rel)
<< SourceRange(OpLoc, rhs->getLocEnd())
<< BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc),
- rhs->getSourceRange(),
Self.PDiag(diag::note_precedence_bitwise_first)
<< BinOp::getOpcodeStr(Opc),
- SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()));
+ SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()),
+ Self.PDiag(diag::note_precedence_bitwise_silence)
+ << BinOp::getOpcodeStr(rhsopc),
+ rhs->getSourceRange());
}
/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
@@ -6532,14 +6459,16 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
case UnaryOperator::OffsetOf:
assert(false && "Invalid unary operator");
break;
-
+
case UnaryOperator::PreInc:
case UnaryOperator::PreDec:
case UnaryOperator::PostInc:
case UnaryOperator::PostDec:
resultType = CheckIncrementDecrementOperand(Input, OpLoc,
Opc == UnaryOperator::PreInc ||
- Opc == UnaryOperator::PostInc);
+ Opc == UnaryOperator::PostInc,
+ Opc == UnaryOperator::PreInc ||
+ Opc == UnaryOperator::PreDec);
break;
case UnaryOperator::AddrOf:
resultType = CheckAddressOfOperand(Input, OpLoc);
@@ -6690,6 +6619,157 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtArg substmt,
return Owned(new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc));
}
+Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ TypeSourceInfo *TInfo,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc) {
+ QualType ArgTy = TInfo->getType();
+ bool Dependent = ArgTy->isDependentType();
+ SourceRange TypeRange = TInfo->getTypeLoc().getSourceRange();
+
+ // We must have at least one component that refers to the type, and the first
+ // one is known to be a field designator. Verify that the ArgTy represents
+ // a struct/union/class.
+ if (!Dependent && !ArgTy->isRecordType())
+ return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type)
+ << ArgTy << TypeRange);
+
+ // Type must be complete per C99 7.17p3 because a declaring a variable
+ // with an incomplete type would be ill-formed.
+ if (!Dependent
+ && RequireCompleteType(BuiltinLoc, ArgTy,
+ PDiag(diag::err_offsetof_incomplete_type)
+ << TypeRange))
+ return ExprError();
+
+ // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
+ // GCC extension, diagnose them.
+ // FIXME: This diagnostic isn't actually visible because the location is in
+ // a system header!
+ if (NumComponents != 1)
+ Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
+ << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
+
+ bool DidWarnAboutNonPOD = false;
+ QualType CurrentType = ArgTy;
+ typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
+ llvm::SmallVector<OffsetOfNode, 4> Comps;
+ llvm::SmallVector<Expr*, 4> Exprs;
+ for (unsigned i = 0; i != NumComponents; ++i) {
+ const OffsetOfComponent &OC = CompPtr[i];
+ if (OC.isBrackets) {
+ // Offset of an array sub-field. TODO: Should we allow vector elements?
+ if (!CurrentType->isDependentType()) {
+ const ArrayType *AT = Context.getAsArrayType(CurrentType);
+ if(!AT)
+ return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
+ << CurrentType);
+ CurrentType = AT->getElementType();
+ } else
+ CurrentType = Context.DependentTy;
+
+ // The expression must be an integral expression.
+ // FIXME: An integral constant expression?
+ Expr *Idx = static_cast<Expr*>(OC.U.E);
+ if (!Idx->isTypeDependent() && !Idx->isValueDependent() &&
+ !Idx->getType()->isIntegerType())
+ return ExprError(Diag(Idx->getLocStart(),
+ diag::err_typecheck_subscript_not_integer)
+ << Idx->getSourceRange());
+
+ // Record this array index.
+ Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd));
+ Exprs.push_back(Idx);
+ continue;
+ }
+
+ // Offset of a field.
+ if (CurrentType->isDependentType()) {
+ // We have the offset of a field, but we can't look into the dependent
+ // type. Just record the identifier of the field.
+ Comps.push_back(OffsetOfNode(OC.LocStart, OC.U.IdentInfo, OC.LocEnd));
+ CurrentType = Context.DependentTy;
+ continue;
+ }
+
+ // We need to have a complete type to look into.
+ if (RequireCompleteType(OC.LocStart, CurrentType,
+ diag::err_offsetof_incomplete_type))
+ return ExprError();
+
+ // Look for the designated field.
+ const RecordType *RC = CurrentType->getAs<RecordType>();
+ if (!RC)
+ return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
+ << CurrentType);
+ RecordDecl *RD = RC->getDecl();
+
+ // C++ [lib.support.types]p5:
+ // The macro offsetof accepts a restricted set of type arguments in this
+ // International Standard. type shall be a POD structure or a POD union
+ // (clause 9).
+ if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
+ DiagRuntimeBehavior(BuiltinLoc,
+ PDiag(diag::warn_offsetof_non_pod_type)
+ << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
+ << CurrentType))
+ DidWarnAboutNonPOD = true;
+ }
+
+ // Look for the field.
+ LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
+ LookupQualifiedName(R, RD);
+ FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
+ if (!MemberDecl)
+ return ExprError(Diag(BuiltinLoc, diag::err_no_member)
+ << OC.U.IdentInfo << RD << SourceRange(OC.LocStart,
+ OC.LocEnd));
+
+ // C99 7.17p3:
+ // (If the specified member is a bit-field, the behavior is undefined.)
+ //
+ // We diagnose this as an error.
+ if (MemberDecl->getBitWidth()) {
+ Diag(OC.LocEnd, diag::err_offsetof_bitfield)
+ << MemberDecl->getDeclName()
+ << SourceRange(BuiltinLoc, RParenLoc);
+ Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
+ return ExprError();
+ }
+
+ // If the member was found in a base class, introduce OffsetOfNodes for
+ // the base class indirections.
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ if (IsDerivedFrom(CurrentType,
+ Context.getTypeDeclType(MemberDecl->getParent()),
+ Paths)) {
+ CXXBasePath &Path = Paths.front();
+ for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
+ B != BEnd; ++B)
+ Comps.push_back(OffsetOfNode(B->Base));
+ }
+
+ if (cast<RecordDecl>(MemberDecl->getDeclContext())->
+ isAnonymousStructOrUnion()) {
+ llvm::SmallVector<FieldDecl*, 4> Path;
+ BuildAnonymousStructUnionMemberPath(MemberDecl, Path);
+ unsigned n = Path.size();
+ for (int j = n - 1; j > -1; --j)
+ Comps.push_back(OffsetOfNode(OC.LocStart, Path[j], OC.LocEnd));
+ } else {
+ Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd));
+ }
+ CurrentType = MemberDecl->getType().getNonReferenceType();
+ }
+
+ return Owned(OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc,
+ TInfo, Comps.data(), Comps.size(),
+ Exprs.data(), Exprs.size(), RParenLoc));
+}
+
Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
SourceLocation BuiltinLoc,
SourceLocation TypeLoc,
@@ -6697,45 +6777,56 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
SourceLocation RPLoc) {
- // FIXME: This function leaks all expressions in the offset components on
- // error.
- // FIXME: Preserve type source info.
- QualType ArgTy = GetTypeFromParser(argty);
- assert(!ArgTy.isNull() && "Missing type argument!");
- bool Dependent = ArgTy->isDependentType();
+ TypeSourceInfo *ArgTInfo;
+ QualType ArgTy = GetTypeFromParser(argty, &ArgTInfo);
+ if (ArgTy.isNull())
+ return ExprError();
+ if (getLangOptions().CPlusPlus) {
+ if (!ArgTInfo)
+ ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
+
+ return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
+ RPLoc);
+ }
+
+ // FIXME: The code below is marked for death, once we have proper CodeGen
+ // support for non-constant OffsetOf expressions.
+
+ bool Dependent = ArgTy->isDependentType();
+
// We must have at least one component that refers to the type, and the first
// one is known to be a field designator. Verify that the ArgTy represents
// a struct/union/class.
if (!Dependent && !ArgTy->isRecordType())
return ExprError(Diag(TypeLoc, diag::err_offsetof_record_type) << ArgTy);
-
+
// FIXME: Type must be complete per C99 7.17p3 because a declaring a variable
// with an incomplete type would be illegal.
-
+
// Otherwise, create a null pointer as the base, and iteratively process
// the offsetof designators.
QualType ArgTyPtr = Context.getPointerType(ArgTy);
Expr* Res = new (Context) ImplicitValueInitExpr(ArgTyPtr);
Res = new (Context) UnaryOperator(Res, UnaryOperator::Deref,
ArgTy, SourceLocation());
-
+
// offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
// GCC extension, diagnose them.
// FIXME: This diagnostic isn't actually visible because the location is in
// a system header!
if (NumComponents != 1)
Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
- << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
-
+ << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
+
if (!Dependent) {
bool DidWarnAboutNonPOD = false;
-
+
if (RequireCompleteType(TypeLoc, Res->getType(),
diag::err_offsetof_incomplete_type))
return ExprError();
-
+
// FIXME: Dependent case loses a lot of information here. And probably
// leaks like a sieve.
for (unsigned i = 0; i != NumComponents; ++i) {
@@ -6746,71 +6837,83 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
if (!AT) {
Res->Destroy(Context);
return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
- << Res->getType());
+ << Res->getType());
}
-
+
// FIXME: C++: Verify that operator[] isn't overloaded.
-
+
// Promote the array so it looks more like a normal array subscript
// expression.
DefaultFunctionArrayLvalueConversion(Res);
-
+
// C99 6.5.2.1p1
Expr *Idx = static_cast<Expr*>(OC.U.E);
// FIXME: Leaks Res
if (!Idx->isTypeDependent() && !Idx->getType()->isIntegerType())
return ExprError(Diag(Idx->getLocStart(),
diag::err_typecheck_subscript_not_integer)
- << Idx->getSourceRange());
-
+ << Idx->getSourceRange());
+
Res = new (Context) ArraySubscriptExpr(Res, Idx, AT->getElementType(),
OC.LocEnd);
continue;
}
-
+
const RecordType *RC = Res->getType()->getAs<RecordType>();
if (!RC) {
Res->Destroy(Context);
return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
- << Res->getType());
+ << Res->getType());
}
-
+
// Get the decl corresponding to this.
RecordDecl *RD = RC->getDecl();
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
DiagRuntimeBehavior(BuiltinLoc,
PDiag(diag::warn_offsetof_non_pod_type)
- << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
- << Res->getType()))
+ << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
+ << Res->getType()))
DidWarnAboutNonPOD = true;
}
-
+
LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
LookupQualifiedName(R, RD);
-
+
FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
// FIXME: Leaks Res
if (!MemberDecl)
return ExprError(Diag(BuiltinLoc, diag::err_no_member)
- << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd));
-
+ << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd));
+
+ // C99 7.17p3:
+ // (If the specified member is a bit-field, the behavior is undefined.)
+ //
+ // We diagnose this as an error.
+ if (MemberDecl->getBitWidth()) {
+ Diag(OC.LocEnd, diag::err_offsetof_bitfield)
+ << MemberDecl->getDeclName()
+ << SourceRange(BuiltinLoc, RPLoc);
+ Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
+ return ExprError();
+ }
+
// FIXME: C++: Verify that MemberDecl isn't a static field.
// FIXME: Verify that MemberDecl isn't a bitfield.
if (cast<RecordDecl>(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) {
Res = BuildAnonymousStructUnionMemberReference(
- OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
+ OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
} else {
PerformObjectMemberConversion(Res, /*Qualifier=*/0,
*R.begin(), MemberDecl);
// MemberDecl->getType() doesn't get the right qualifiers, but it
// doesn't matter here.
Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd,
- MemberDecl->getType().getNonReferenceType());
+ MemberDecl->getType().getNonReferenceType());
}
}
}
-
+
return Owned(new (Context) UnaryOperator(Res, UnaryOperator::OffsetOf,
Context.getSizeType(), BuiltinLoc));
}
@@ -7127,7 +7230,7 @@ Sema::OwningExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
}
-static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
+static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
Expr *SrcExpr, FixItHint &Hint) {
if (!SemaRef.getLangOptions().ObjC1)
return;
@@ -7155,7 +7258,11 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
- Expr *SrcExpr, AssignmentAction Action) {
+ Expr *SrcExpr, AssignmentAction Action,
+ bool *Complained) {
+ if (Complained)
+ *Complained = false;
+
// Decode the result (notice that AST's are still created for extensions).
bool isInvalid = false;
unsigned DiagKind;
@@ -7218,8 +7325,30 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
break;
}
- Diag(Loc, DiagKind) << DstType << SrcType << Action
+ QualType FirstType, SecondType;
+ switch (Action) {
+ case AA_Assigning:
+ case AA_Initializing:
+ // The destination type comes first.
+ FirstType = DstType;
+ SecondType = SrcType;
+ break;
+
+ case AA_Returning:
+ case AA_Passing:
+ case AA_Converting:
+ case AA_Sending:
+ case AA_Casting:
+ // The source type comes first.
+ FirstType = SrcType;
+ SecondType = DstType;
+ break;
+ }
+
+ Diag(Loc, DiagKind) << FirstType << SecondType << Action
<< SrcExpr->getSourceRange() << Hint;
+ if (Complained)
+ *Complained = true;
return isInvalid;
}
@@ -7328,8 +7457,13 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
// (e.g. (void)sizeof()) constitute a use for warning purposes (-Wunused-variables and
// -Wunused-parameters)
if (isa<ParmVarDecl>(D) ||
- (isa<VarDecl>(D) && D->getDeclContext()->isFunctionOrMethod()))
+ (isa<VarDecl>(D) && D->getDeclContext()->isFunctionOrMethod())) {
D->setUsed(true);
+ return;
+ }
+
+ if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D))
+ return;
// Do not mark anything as "used" within a dependent context; wait for
// an instantiation.
@@ -7375,7 +7509,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
MethodDecl->getOverloadedOperator() == OO_Equal) {
if (!MethodDecl->isUsed())
- DefineImplicitOverloadedAssign(Loc, MethodDecl);
+ DefineImplicitCopyAssignment(Loc, MethodDecl);
}
}
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
@@ -7536,12 +7670,12 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
SourceLocation Open = E->getSourceRange().getBegin();
SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
- Diag(Loc, diagnostic)
- << E->getSourceRange()
- << FixItHint::CreateInsertion(Open, "(")
- << FixItHint::CreateInsertion(Close, ")");
+ Diag(Loc, diagnostic) << E->getSourceRange();
Diag(Loc, diag::note_condition_assign_to_comparison)
<< FixItHint::CreateReplacement(Loc, "==");
+ Diag(Loc, diag::note_condition_assign_silence)
+ << FixItHint::CreateInsertion(Open, "(")
+ << FixItHint::CreateInsertion(Close, ")");
}
bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {
OpenPOWER on IntegriCloud