diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 7 | ||||
-rw-r--r-- | test/SemaCXX/offsetof.cpp | 15 |
3 files changed, 24 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0cbbfc750b..c9bdf13b30 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -936,6 +936,8 @@ def err_offsetof_record_type : Error< def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">; def ext_offsetof_extended_field_designator : Extension< "using extended field designator is an extension">; +def err_offsetof_non_pod_type : Error<"offset of on non-POD type %0">; + def warn_floatingpoint_eq : Warning< "comparing floating point with == or != is unsafe">, InGroup<DiagGroup<"float-equal">>, DefaultIgnore; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bf9947a5e2..3442cc1db9 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4761,6 +4761,13 @@ 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()) + return ExprError(Diag(BuiltinLoc, diag::err_offsetof_non_pod_type) + << SourceRange(CompPtr[0].LocStart, OC.LocEnd) + << Res->getType()); + } + FieldDecl *MemberDecl = dyn_cast_or_null<FieldDecl>(LookupQualifiedName(RD, OC.U.IdentInfo, LookupMemberName) diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp new file mode 100644 index 0000000000..726dc7e527 --- /dev/null +++ b/test/SemaCXX/offsetof.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct NonPOD { + virtual void f(); + int m; +}; + +struct P { + NonPOD fieldThatPointsToANonPODType; +}; + +void f() { + int i = __builtin_offsetof(P, fieldThatPointsToANonPODType.m); // expected-error{{offset of on non-POD type 'struct P'}} +} + |