Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion core/clingutils/src/TClingUtils.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1979,7 +1979,7 @@ void ROOT::TMetaUtils::WriteClassInit(std::ostream& finalString,
if (HasCustomStreamerMemberFunction(cl, decl, interp, normCtxt)) {
rootflag = rootflag | TClassTable__kHasCustomStreamerMember;
}
finalString << "isa_proxy, " << rootflag << "," << "\n" << " sizeof(" << csymbol << ") );" << "\n";
finalString << "isa_proxy, " << rootflag << "," << "\n" << " sizeof(" << csymbol << "), alignof(" << csymbol << ") );" << "\n";
if (HasIOConstructor(decl, args, ctorTypes, interp)) {
finalString << " instance.SetNew(&new_" << mappedname.c_str() << ");" << "\n";
if (args.size()==0 && NeedDestructor(decl, interp))
Expand Down Expand Up @@ -2041,6 +2041,10 @@ void ROOT::TMetaUtils::WriteClassInit(std::ostream& finalString,
// FIXME Workaround: for the moment we do not generate coll proxies with unique ptrs since
// they imply copies and therefore do not compile.
auto classNameForIO = TClassEdit::GetNameForIO(classname);

finalString << " static_assert(alignof(" << csymbol << "::value_type) <= 4096,\n";
finalString << " \"Class with alignment strictly greater than 4096 are currently not supported in CollectionProxy. \"\n";
finalString << " \"Please report this case to the developers\");\n";
finalString << " instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" << methodTCP << "< " << classNameForIO.c_str() << " >()));" << "\n";

needCollectionProxy = true;
Expand Down
3 changes: 3 additions & 0 deletions core/meta/inc/TClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ friend class TStreamerInfo;
//Wrapper around this class custom conversion Streamer member function.
ClassConvStreamerFunc_t fConvStreamerFunc = nullptr;
Int_t fSizeof = -1; //Sizeof the class.
std::size_t fAlignment = 0; //Alignment of the class (0 for unknown alignment)

std::atomic<Char_t> fCanSplit = -1; ///<!Indicates whether this class can be split or not. Values are -1, 0, 1, 2

Expand Down Expand Up @@ -313,6 +314,7 @@ friend class TStreamerInfo;

void SetClassVersion(Version_t version);
void SetClassSize(Int_t sizof) { fSizeof = sizof; }
void SetClassAlignment(std::size_t align) { fAlignment = align; }
TVirtualStreamerInfo* DetermineCurrentStreamerInfo();

void SetStreamerImpl(Int_t streamerType);
Expand Down Expand Up @@ -435,6 +437,7 @@ friend class TStreamerInfo;
return fClassVersion;
}
Int_t GetClassSize() const { return Size(); }
size_t GetClassAlignment() const;
TDataMember *GetDataMember(const char *datamember) const;
Longptr_t GetDataMemberOffset(const char *membername) const;
const char *GetDeclFileName() const;
Expand Down
5 changes: 3 additions & 2 deletions core/meta/inc/TGenericClassInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ namespace ROOT {
ClassConvStreamerFunc_t fConvStreamerFunc;
TVirtualCollectionProxy *fCollectionProxy;
Int_t fSizeof;
std::size_t fAlignment;
Int_t fPragmaBits;
Detail::TCollectionProxyInfo *fCollectionProxyInfo;
Detail::TCollectionProxyInfo *fCollectionStreamerInfo;
Expand All @@ -80,13 +81,13 @@ namespace ROOT {
const char *declFileName, Int_t declFileLine,
const std::type_info &info, const Internal::TInitBehavior *action,
DictFuncPtr_t dictionary,
TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof);
TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof, std::size_t alignof_ = 0);

TGenericClassInfo(const char *fullClassname, Int_t version,
const char *declFileName, Int_t declFileLine,
const std::type_info &info, const Internal::TInitBehavior *action,
DictFuncPtr_t dictionary,
TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof);
TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof, std::size_t alignof_ = 0);

TGenericClassInfo(const char *fullClassname, Int_t version,
const char *declFileName, Int_t declFileLine,
Expand Down
1 change: 1 addition & 0 deletions core/meta/inc/TInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ class TInterpreter : public TNamed {
virtual void *ClassInfo_New(ClassInfo_t * /* info */, void * /* arena */) const {return nullptr;}
virtual Long_t ClassInfo_Property(ClassInfo_t * /* info */) const {return 0;}
virtual int ClassInfo_Size(ClassInfo_t * /* info */) const {return 0;}
virtual size_t ClassInfo_AlignOf(ClassInfo_t * /* info */) const {return 0;}
virtual Longptr_t ClassInfo_Tagnum(ClassInfo_t * /* info */) const {return 0;}
virtual const char *ClassInfo_FileName(ClassInfo_t * /* info */) const {return nullptr;}
virtual const char *ClassInfo_FullName(ClassInfo_t * /* info */) const {return nullptr;}
Expand Down
1 change: 1 addition & 0 deletions core/meta/inc/TVirtualStreamerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class TVirtualStreamerInfo : public TNamed {
TVirtualStreamerInfo();
TVirtualStreamerInfo(TClass * /*cl*/);
virtual ~TVirtualStreamerInfo();
virtual size_t GetClassAlignment() const = 0;
virtual void Build(Bool_t isTransient = kFALSE) = 0;
virtual void BuildCheck(TFile *file = nullptr, Bool_t load = kTRUE) = 0;
virtual void BuildEmulated(TFile *file) = 0;
Expand Down
25 changes: 25 additions & 0 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -5753,6 +5753,31 @@ void TClass::SetCurrentStreamerInfo(TVirtualStreamerInfo *info)
fCurrentInfo = info;
}

////////////////////////////////////////////////////////////////////////////////
/// Return the alignment requirement (in bytes) for objects of this class.
///
/// Returns (size_t)-1 if the class info is invalid, 0 for a forward-declared
/// class, an enum, a namespace or or a class with no definition. For all other
/// cases the actual alignment obtained from the dictionary or the clang ASTRecordLayout,
/// or the StreamerInfo (in that order of priority) is returned.
///
/// Returns `0` when the alignment cannot be determined.

size_t TClass::GetClassAlignment() const
{
if (fAlignment != 0)
return fAlignment;
if (fState < kEmulated || Property() & (kIsNamespace|kIsEnum))
return 0;
// FIX-ALIGN: do we need to have something special for collection proxy?
//if (fCollectionProxy)
// return fCollectionProxy->AlignOf();
Comment on lines +5772 to +5774
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to resolve the question in this PR.

if (HasInterpreterInfo()) {
return gCling->ClassInfo_AlignOf(GetClassInfo());
}
return GetStreamerInfo()->GetClassAlignment();
}

////////////////////////////////////////////////////////////////////////////////
/// Return size of object of this class.

Expand Down
11 changes: 6 additions & 5 deletions core/meta/src/TGenericClassInfo.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ namespace Internal {
const char *declFileName, Int_t declFileLine,
const std::type_info &info, const Internal::TInitBehavior *action,
DictFuncPtr_t dictionary,
TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof)
TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof, std::size_t alignof_)
: fAction(action), fClass(nullptr), fClassName(fullClassname),
fDeclFileName(declFileName), fDeclFileLine(declFileLine),
fDictionary(dictionary), fInfo(info),
fImplFileName(nullptr), fImplFileLine(0),
fIsA(isa),
fVersion(1),
fMerge(nullptr),fResetAfterMerge(nullptr),fNew(nullptr),fNewArray(nullptr),fDelete(nullptr),fDeleteArray(nullptr),fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamer(nullptr),
fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(sizof), fPragmaBits(pragmabits),
fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(sizof), fAlignment(alignof_), fPragmaBits(pragmabits),
fCollectionProxyInfo(nullptr), fCollectionStreamerInfo(nullptr)
{
// Constructor.
Expand All @@ -107,15 +107,15 @@ namespace Internal {
const char *declFileName, Int_t declFileLine,
const std::type_info &info, const Internal::TInitBehavior *action,
DictFuncPtr_t dictionary,
TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof)
TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof, std::size_t alignof_)
: fAction(action), fClass(nullptr), fClassName(fullClassname),
fDeclFileName(declFileName), fDeclFileLine(declFileLine),
fDictionary(dictionary), fInfo(info),
fImplFileName(nullptr), fImplFileLine(0),
fIsA(isa),
fVersion(version),
fMerge(nullptr),fResetAfterMerge(nullptr),fNew(nullptr),fNewArray(nullptr),fDelete(nullptr),fDeleteArray(nullptr),fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamer(nullptr),
fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(sizof), fPragmaBits(pragmabits),
fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(sizof), fAlignment(alignof_), fPragmaBits(pragmabits),
fCollectionProxyInfo(nullptr), fCollectionStreamerInfo(nullptr)

{
Expand All @@ -137,7 +137,7 @@ namespace Internal {
fIsA(nullptr),
fVersion(version),
fMerge(nullptr),fResetAfterMerge(nullptr),fNew(nullptr),fNewArray(nullptr),fDelete(nullptr),fDeleteArray(nullptr),fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamer(nullptr),
fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(0), fPragmaBits(pragmabits),
fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(0), fAlignment(0), fPragmaBits(pragmabits),
fCollectionProxyInfo(nullptr), fCollectionStreamerInfo(nullptr)

{
Expand Down Expand Up @@ -295,6 +295,7 @@ namespace Internal {
}
}
fClass->SetClassSize(fSizeof);
fClass->SetClassAlignment(fAlignment);

//---------------------------------------------------------------------
// Attach the schema evolution information
Expand Down
8 changes: 8 additions & 0 deletions core/metacling/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -8260,6 +8260,14 @@ std::string TCling::CallFunc_GetWrapperCode(CallFunc_t *func) const
// ClassInfo interface
//

////////////////////////////////////////////////////////////////////////////////

size_t TCling::ClassInfo_AlignOf(ClassInfo_t* cinfo) const
{
TClingClassInfo* TClinginfo = (TClingClassInfo*) cinfo;
return TClinginfo->GetAlignOf();
}

////////////////////////////////////////////////////////////////////////////////
/// Return true if the entity pointed to by 'declid' is declared in
/// the context described by 'info'. If info is null, look into the
Expand Down
1 change: 1 addition & 0 deletions core/metacling/src/TCling.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ class TCling final : public TInterpreter {
void* ClassInfo_New(ClassInfo_t* info, void* arena) const final;
Long_t ClassInfo_Property(ClassInfo_t* info) const final;
int ClassInfo_Size(ClassInfo_t* info) const final;
size_t ClassInfo_AlignOf(ClassInfo_t* info) const final;
Longptr_t ClassInfo_Tagnum(ClassInfo_t* info) const final;
const char* ClassInfo_FileName(ClassInfo_t* info) const final;
const char* ClassInfo_FullName(ClassInfo_t* info) const final;
Expand Down
47 changes: 47 additions & 0 deletions core/metacling/src/TClingClassInfo.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,12 @@ int TClingClassInfo::RootFlag() const
return 0;
}

/// Return the size of the class in bytes as reported by clang.
///
/// Returns -1 if the class info is invalid, 0 for a forward-declared class,
/// an enum, or a class with no definition, and 1 for a namespace (a special
/// value inherited from CINT). For all other cases the actual byte size
/// obtained from the clang ASTRecordLayout is returned.
int TClingClassInfo::Size() const
{
if (!IsValid()) {
Expand Down Expand Up @@ -1355,6 +1361,47 @@ int TClingClassInfo::Size() const
return clang_size;
}

/// Return the alignment of the class in bytes as reported by clang.
///
/// Returns (size_t)-1 if the class info is invalid, 0 for a forward-declared
/// class, an enum, a namespace or or a class with no definition. For all other
/// cases the actual alignment obtained from the clang ASTRecordLayout is
/// returned.
size_t TClingClassInfo::GetAlignOf() const
{
if (!IsValid()) {
return -1;
}
if (!GetDecl()) {
// A forward declared class.
return 0;
}

R__LOCKGUARD(gInterpreterMutex);

Decl::Kind DK = GetDecl()->getKind();
if (DK == Decl::Namespace) {
return 0;
}
else if (DK == Decl::Enum) {
return 0;
}
const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
if (!RD) {
return -1;
}
if (!RD->getDefinition()) {
// Forward-declared class.
return 0;
}
ASTContext &Context = GetDecl()->getASTContext();
cling::Interpreter::PushTransactionRAII RAII(fInterp);
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
auto align = Layout.getAlignment().getQuantity();
assert(align > 0);
return align;
}

Longptr_t TClingClassInfo::Tagnum() const
{
if (!IsValid()) {
Expand Down
1 change: 1 addition & 0 deletions core/metacling/src/TClingClassInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class TClingClassInfo final : public TClingDeclInfo {
long Property() const;
int RootFlag() const;
int Size() const;
size_t GetAlignOf() const;
Longptr_t Tagnum() const;
const char *FileName();
void FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const;
Expand Down
Loading
Loading